﻿#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include  <assert.h>
//#include <stdio.h>

//int main()
//{	
//	
//	int a = 10;
//	int* p = &a;
//	printf("你好，Hello.world!\n");
//	return 0;
//}

//typedef unsigned int u_int32; //typedef类型重命名
//#include <stdio.h>
//int main()
//{
//	u_int32 age = 10;
//	printf("%d Hello, world!\n", age);
//	return	0;
//}


//struct Stu
//{
//	char name[20];
//	int  age;
//	char sex[10];
//	char telephone[20];
//};


//void print(struct Stu* ps)
//{
//	printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).telephone);
//	printf("%s %d %s %s\n", ps->name, ps->age, ps->sex, ps->telephone);
//
//}
//int main()
//{
//	struct Stu s = { "张三", 20, "男", "15507653673" };
//	//printf("%s %d %s %s", s.name, s.age, s.sex, s.telephone);
//	print(&s);
//	return 0;
//} 


//int main()
//{
//	int a = 0;
//	int b = 2;
//	if (a == 1)
//		if (b == 2)
//			printf("呵呵\n");
//		else
//			printf("哈哈\n");
//	return 0;
//}

//int main()
//{
//	int num = 3;
//	if (5 == num)   // 这是推荐写法 
//	//if(num = 5)   不推荐写法
//		printf("ok\n");
//	else
//	{
//		printf("no ok\n");
//	}
//}



//int main()
//{
//	int a = 0;
//	scanf("%d", &a);
//	if (a % 2 != 0)
//	{
//		printf("是奇数");
//	}
//	else
//	{
//		printf("不是奇数");
//	}
//
//	return 0;
//}


//int main()
//{
//	int i = 1;
//	for (i = 1; i <= 100; i++)
//	{
//		if (i % 2 == 1)
//			printf("%d ", i);
//		else
//			continue;
//	}
//	return 0;
//}


//int main()
//{
//	//float day = 0.0f;
//	//scanf("%f", &day);
//	int day = 0;
//	scanf("%d", &day);
//	/*if (1 == day)
//		printf("星期一\n");
//	else if (2 == day)
//		printf("星期二\n");
//	else if (3 == day)
//		printf("星期三\n");
//	else if (4 == day)
//		printf("星期四\n");
//	else if (5 == day)
//		printf("星期五\n");
//	else if (6 == day)
//		printf("星期六\n");
//	else if (7 == day)
//		printf("星期日\n");*/
//	switch(day)					//day 必须为整型表达式
//	{
//	case 1:
//		printf("星期一\n");
//		break;
//	case 2:
//		printf("星期二\n");
//		break;
//	case 3:
//		printf("星期三\n");
//		break;
//	case 4:
//		printf("星期四\n");
//		break;
//	case 5:
//		printf("星期五\n");
//		break;
//	case 6:
//		printf("星期六\n");
//		break;
//	case 7:
//		printf("星期日\n");
//		break;
//	}
//	return 0;
//}


//int main()
//{
//	int day = 0;
//	scanf("%d", &day);
//	switch (day)
//	{
//	case 1:
//	case 2:
//	case 3:
//	case 4:
//	case 5:
//		printf("weekday!");
//		break;
//	case 6:
//	case 7:
//		printf("weekend!");
//		break;
//	default:  //不符合所有case的情况，则走default
//		printf("选择错误!");
//		break;
//	}
//	return 0;
//}


//int main()
//{
//	int n = 1;
//	int m = 2;
//	switch (n)
//	{
//	case 1:
//		m++;   // m = 3
//	case 2:
//		n++;  //n =2
//	case 3:				 // 可以嵌套switch语句
//		switch (n)
//		{
//		case 1:
//			n++;
//		case 2:
//			m++;  // m = 4
//			n++;  // n = 3
//			break;
//		}
//
//	case 4:
//		m++;     // m = 5
//		break;
//	default:
//		break;
//	}
//	printf("m = %d, n = %d\n", m, n);
//	return 0;
//}


//int main()
//{
//	int i = 0;
//	for (i = 0; i <= 10; i++)
//	{
//		if (i = 5)
//			printf("%d ", i);
//	}
//	return 0;
//}

/*
最大公约数：即两个数据中公共约数的最大者。
求解的方式比较多，暴力穷举、辗转相除法、更相减损法、Stein算法算法
此处主要介绍：辗转相除法


思路：
例子：18和24的最大公约数
第一次：a = 18  b = 24  c = a%b = 18%24 = 18
	  循环中：a = 24   b=18
第二次：a = 24   b = 18  c = a%b = 24%18 = 6
	  循环中：a = 18   b = 6


第三次：a = 18   b = 6   c=a%b = 18%6 = 0
  循环结束

此时b中的内容即为两个数中的最大公约数。
*/


//int main()
//{
//	int a = 0;
//	int b = 0;
//	int c = 0;
//	scanf("%d %d", &a, &b);
//
//	while (c = a % b)
//	{
//		a = b;
//		b = c;
//	}
//	printf("%d\n", b);
//	return 0;
//}

/*
思路：
要求1000年到2000年之间的闰年，只需要知道求解闰年的方法即可。
闰年的条件：如果N能够被4整除，并且不能被100整除，则是闰年
		   或者：N能被400整除，也是闰年
	 即：4年一润并且百年不润，每400年再润一次
*/
//int main()
//{
//	int a = 0;
//	for (a = 1000;  a <= 2000; a++)
//	{
//		if (((a % 4 == 0) && (a % 100 != 0)) || (a % 400 == 0))
//		{
//			printf("%d ", a);
//		}
//	}
//	return 0;
//}

/*
打印素数
*/

//int main()
//{
//	int a = 0;
//	int count = 0;
//	for (a = 100; a <= 200; a++)
//	{
//		int b = 0;
//		for (b = 2; b < a; b++)
//		{
//			if (a % b == 0)
//			{
//				break;
//			}
//		}
//		if (a == b)
//		{
//			count++;
//			printf("%d \n", a);
//		}
//	}
//	printf("count=%d\n", count);
//	return 0;
//}

/*
从大到小输出
三个数比较大小
*/

//int main()
//{
//	int a = 0;
//	int b = 0;
//	int c = 0;
//	scanf("%d %d %d", &a, &b, &c);
//	if (a < b)
//	{
//		int tmp = a;
//		a = b;
//		b = tmp;
//	}
//	if (a < c)
//	{
//		int tmp = a;
//		a = c;
//		c = tmp;
//	}
//	if (b < c)
//	{
//		int tmp = b;
//		b = c;
//		c = tmp;
//	}
//	printf("%d %d %d", a, b, c);
//	return 0;
//}

/*
打印3的倍数的数
*/
//int main()
//{
//	int a = 0;
//	int count = 0;
//	for (a = 1; a <= 100; a++)
//	{
//		if (a % 3 == 0)
//		{
//			count++;
//			printf("%d ", a);
//		}
//		
//	}
//	printf("count = %d\n", count);
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int a = 0, b = 0;
//	for (a = 1, b = 1; a <= 100; a++)
//	{
//		if (b >= 20) break;
//		if (b % 3 == 1)
//		{
//			b = b + 3;
//			continue;
//		}
//		b = b - 5;
//	}
//	printf("%d\n", a);
//	return 0;
//}


//int main()
//{
//	int a = 1;
//	while (a <= 10)
//	{
//		printf("%d ", a);
//		a++;
//	}
//	return 0;
//
//}


//int main()
//{
//	int ch = 0;
//	while (((ch = getchar()) != EOF))
//	{
//		putchar(ch);
//	}
//	return 0;
//}

//int main()
//{
//	char password[20] = { 0 };
//	int ch = 0;
//	printf("请输入密码->");
//	scanf("%s", password);    //输入一串字符后，获取空格之前的值,不获取\n
//	//int ret = getchar();      //这时候缓冲区剩余\n,被ret获取到，则直接打印No
//	while (((ch = getchar()) != '\n'))  //使用getchar来读取、清理缓冲区中的字符
//	{
//
//	}
//	printf("请确认密码（Y/N）:>");
//	int ret = getchar();
//	putchar(ret);
//	if ('Y' == ret)
//	{
//		printf("Yes\n");
//	}
//	else
//	{
//		printf("No\n");
//	}
//	return 0;
//}


/*
转换以下ASCII码为对应字符并输出他们:
73, 32, 99, 97, 110, 32, 100, 111, 32, 105, 116 , 33
*/


//#include <stdio.h>

//int main()
//{
//	int arr[] = { 73, 32, 99, 97, 110, 32, 100, 111, 32, 105, 116 , 33 };
//	int len = sizeof(arr) / sizeof(arr[0]);   //计算数组arr中元素个数
//	int count = 0;
//	while (count < len)
//	{
//		printf("%c", arr[count]);
//		count++;
//	}
//	return 0;
//}


/*
输入描述：
输入只有一行，出生日期，包括年月日，年月日之间的数字没有分隔符。
输出描述：
三行，第一行为出生年份，第二行为出生月份，第三行为出生日期。输出时如果月份或天数为1位数，需要在1位数前面补0。

备注：
通过scanf函数的%m格式控制可以指定输入域宽，输入数据域宽（列数），按此宽度截取所需数据；
通过printf函数的%0格式控制符，输出数值时指定左面不使用的空位置自动填0。
*/

//
//#include <stdio.h>
//
//
//int main()
//{
//	int year = 0;
//	int month = 0;
//	int day = 0;
//	scanf("%4d%2d%2d", &year, &month, &day);
//
//	printf("year=%4d\nmonth=%02d\ndate=%02d", year, month, day);
//	return 0;
//
//}



/*
* 描述
依次输入一个学生的学号，以及3科（C语言，数学，英语）成绩，在屏幕上输出该学生的学号，3科成绩（注：输出成绩时需进行四舍五入且保留2位小数）。

输入描述：
学号以及3科成绩，学号和成绩之间用英文分号隔开，成绩之间用英文逗号隔开。

输出描述：
学号，3科成绩，输出格式详见输出样例。

示例1
输入：
17140216;80.845,90.55,100.00
输出：
The each subject score of No. 17140216 is 80.85, 90.55, 100.00.
*/

//#include <stdio.h>

//int main()
//{
//	int No = 0;
//	float c = 0.0f;
//	float math = 0.0f;
//	float english = 0.0f;
//
//	scanf("%d;%f,%f,%f", &No, &c, &math, &english);
//	printf("The each subject score of No. %d is %.2f, %.2f, %.2f.", No, c, math, english);
//	return 0;
//
//}


/*
输入描述：
无
输出描述：
包括两行：
第一行为“Hello world!”
第二行为printf(“Hello world!”)调用后的返回值。
*/

//#include <stdio.h>

//int main()
//{
//	int a = printf("Hello world!");
//	printf("\n%d", a);
//	return 0;
//
//
//}

/*
输入描述：
无
输出描述：
printf("Hello world!\n");
cout << "Hello world!" << endl;
*/

//#include <stdio.h>

//int main()
//{
//	printf("printf(\"Hello world!\\n\");\n");   //转义字符
//	printf("cout << \"Hello world!\" << endl;");
//	return 0;
//}


/*
输入描述：
一行，4个整数，用空格分开。
输出描述：
一行，一个整数，为输入的4个整数中最大的整数。

输入：
5 8 2 5
输出：
8
*/

// 通用方法，找出若干个数的最大值
//方法1：
//#include <stdio.h>
//int main()
//{
//    int arr[4] = { 0 };
//    int i = 0;
//    while (i < 4)
//    {
//        scanf("%d", &arr[i]);
//        i++;
//    }
//
//    int max = arr[0];
//    int a = 0;
//    while (a < 4)
//    {
//        if (max < arr[a])
//        {
//            max = arr[a];
//        }
//        a++;
//    }
//    printf("%d\n", max);
//    return 0;
//}

//方法2
//#include <stdio.h>
//int main()
//{
//	int n = 0;
//	int max = 0;
//	int i = 1;
//
//	scanf("%d", &max);
//
//	while (i < 4)
//	{
//		scanf("%d", &n);
//		if (n > max)
//		{
//			max = n;
//		}
//		i++;
//	}
//	printf("%d", max);
//	return 0;
//}



/*
给定一个球体的半径，计算其体积。其中球体体积公式为 V = 4/3*πr3，其中 π = 3.1415926
数据范围：输入一个浮点值 0 \le n \le 15 \0≤n≤15

输入描述：
一行，用浮点数表示的球体的半径。

输出描述：
一行，球体的体积，小数点后保留3位。
*/

# include <stdio.h>
# define PI  3.1415926

//int main()
//{
//	float r = 0.0f;
//	scanf("%f", &r);
//	printf("%.3f", ((4 / 3.0) * PI * r * r * r));
//	return 0;
//
//}


/*
输入描述：
一行，两个整数，分别表示体重（公斤），身高（厘米），中间用一个空格分隔。
输出描述：
一行，BMI指数（保留两位小数）

BMI = 体重公斤数除以身高米数平方
*/

//#include <stdio.h>
//int main()
//{
//	int weight = 0;
//	int high = 0;
//	scanf("%d %d", &weight, &high);
//	printf("%.2f", (weight / ((high / 100.0) * (high / 100.0))));
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int i = 1;
//	for (i = 1; i <= 10; i++)
//	{
//		printf("%d\n", i);
//	}
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int i = 0;  
//	for (; ;)    //判断部分省略后，即为死循环
//	{
//		printf("Hello!\n");
//	}
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int i = 0;
//	int j = 0;
//	for (; i < 2; i++)
//	{	
//		for (; j < 2; j++)  //由于没有初始化部分，第一次走完这个循环后，j一直为2，那么到i=1时再次进入此循环，
							// 由于j=2不小于2，所有不会打印内容
//		{
//			printf("Hello, world!\n");
//		}
//	}
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int x, y;
//	for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
//	{
//		printf("Hello,world!\n");
//
//	}
//	return 0;
//}



//#include <stdio.h>
//int main()
//{
//	int i = 0;
//	int k = 0;
//	for (i = 0, k = 0; k = 0; i++, k++) //判断部分，k=0为假，所以不会进入循环
//	{
//		printf("进入循环！");
//		k++;
//	}
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int i = 1;
//	do
//	{
//		printf("%d\n", i);
//		i++;
//	} while (i <= 10);
//
//	return 0;
//}

//计算 n的阶乘
//1*2*3*...*n

//#include <stdio.h>
//int main()
//{
//	int n = 0;
//	int ret = 1;
//	int i = 0;
//	scanf("%d", &n);
//	for (i = 1; i <= n; i++)
//	{
//		ret = ret * i;
//
//	}
//	printf("%d", ret);
//	return 0;
//}




//计算 1！+ 2！+ 3！ + 4！+ 5！+ ... + 10！
//#include <stdio.h>
//int main()
//{
//	int n = 0;
//	int i = 1;
//	int j = 0;
//	int sum = 0;
//	int ret = 1;
//	for (j = 1; j <= 10; j++)
//	{	
//		//int result = 1;
//		//for (i = 1; i <= j; i++)
//		//{
//		//	result = result * i;
//		//}
//		//sum = sum + result;
//		ret = ret * j;
//		sum = sum + ret;
//	}
//	printf("%d", sum);
//	return 0;
//}


//在一个有序数组中查找具体的某个数字n。（讲解二分查找）
//方法一：效率低
//#include <stdio.h>
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int len = sizeof(arr) / sizeof(arr[0]);
//	int k = 1;
//	int i = 0;
//	for (i = 0; i < len; i++)
//	{
//		if (k == arr[i])
//		{
//			printf("找到了，下标为%d\n", i);
//			break;
//		}
//
//	} 
//	if (i == len)
//	{
//		printf("找不到");
//	}
//	return 0;
//}



//方法二：折半查找
//#include <stdio.h>
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int len = sizeof(arr) / sizeof(arr[0]);
//	int k = 1;
//
//	int left = 0;
//	int right = len - 1;
//	while (left <= right)
//	{
//		int mid = (left + right) / 2;
//		if (arr[mid] < k)
//		{
//			left = mid + 1;
//		}
//		else if (arr[mid] > k)
//		{
//			right = mid - 1;
//		}
//		else
//		{
//			printf("找到了，下标为%d", mid);
//			break;
//		}
//		if (left > right)
//		{
//			printf("找不到");
//		}
//
//	}
//	return 0;
//}


//编写代码，演示多个字符从两端移动，向中间汇聚。
//#include <stdio.h>
//#include <string.h>
//#include <windows.h>
//#include <stdlib.h>
//int main()
//{
//	char arr1[] = "welcome to bit !!!";
//	char arr2[] = "##################";
//
//	int left = 0;
//	int right = strlen(arr1) - 1 ;
//
//	while (left <= right)
//	{
//		arr2[left] = arr1[left];
//		arr2[right] = arr1[right];
//		left++;
//		right--;
//		Sleep(100);
//		system("cls");			//执行windows系统清除命令
//		printf("%s\n", arr2);
//	}
//	return 0;
//}

//编写代码实现，模拟用户登录情景，并且只能登录三次。（只允许输入三次密码，
//如果密码正确,则提示登录成功，如果三次均输入错误，则退出程序。


//#include <stdio.h>
//#include <string.h>
//int main()
//{
//	int i = 0;
//	char str1[20] = { 0 };
//	for (i = 0; i < 3; i++)
//	{
//		printf("请输入密码:>");
//		scanf("%s", str1);
//		if (!(strcmp(str1, "abcdefg"))) //字符串比较库函数strcmp()
//		{
//			printf("登陆成功!\n");
//			break;
//
//		}
//		else
//		{
//			printf("密码错误!\n");
//		}
//	}
//	if (i == 3)
//	{
//		printf("三次密码均输入错误，退出程序");
//	}
//	return 0;
//
//}

//猜字游戏
//#include <stdio.h>
//#include <stdlib.h>
//#include <time.h>
//
//void menu()
//{
//	printf("*********************************\n");
//	printf("***********  1.play   ***********\n");
//	printf("***********  0.exit   ***********\n");
//	printf("*********************************\n");
//
//}
//
//
//void game()
//{
//	int random_num = rand() % 100 + 1;
//	int input = 0;
//	while (1)
//	{
//		printf("请输入猜的数字>");
//		scanf("%d", &input);
//		//printf("随机数 = %d\n", random_num);
//		if (input < random_num)
//		{
//			printf("猜小了\n");
//		}
//		else if (input > random_num)
//		{
//			printf("猜大了\n");
//		}
//		else
//		{
//			printf("猜对了\n");
//			break;
//		}
//
//	}
//}
//
//int main()
//{
//	int input = 0;
//	srand((unsigned int )time(NULL));   //使用time()作为参数设置随机数，每次随机数都会不一样
//	do
//	{	
//		menu();
//		printf("请选择->");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			game();
//			break;
//		case 0:
//			break;
//		default:
//			printf("选择错误，请重新选择\n");
//			break;
//		}
//	} while (input);
//	return	0;
//}

//#include <stdio.h>
//int main()
//{
//again:
//	printf("Hello, world\n");
//	printf("Hello, boy\n");
//	goto again;              //程序从上往下执行，goto实现循环
//	return 0;
//
//}

//一个关机程序
//#include <string.h>
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//	char chr[20] = { 0 };
//	//system("shutdown -s -t 60");
//again:
//	printf("请注意，你的电脑将在60秒内关机，如果输入：取消关机，则不会关机\n");
//	scanf("%s", chr);
//	if (strcmp(chr, "取消关机") == 0)
//	{
//		//system("shutdown -a");
//	}
//	else
//	{
//		goto again;
//	}
//	return 0;
//}

//函数
//#include <stdio.h>
//#include <string.h>
//
//int main()
//{
//	//char arr1[20] = { 0 };
//	//char arr2[] = "Hello, bit";
//	//strcpy(arr1, arr2);   //字符串复制
//	//printf("%s", arr1);
//
//	char arr[] = "Hello, world!";
//	memset(arr, '/', 5);   //设置内存字符串：对arr字符数组的前5个字符换成"\"
//	printf("%s", arr);
//	return 0;
//
//}

//void swap(int x, int y)
//{
//	int tmp = 0;
//	tmp = x;
//	x = y;
//	y = tmp;
//}
//
//void swap_2(int* x, int* y)
//{
//	int tmp = 0;
//	tmp = *x;
//	*x = *y;
//	*y = tmp;
//}
//
//#include <stdio.h>
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	printf("交换前a = %d, b = %d\n", a, b);
//	//swap(a, b);
//	swap_2(&a, &b);       //传递指针来修改实参的数值    地址是内存分配的，自己修改地址的做法没什么意义
//	printf("交换后a = %d, b = %d\n", a, b); 
//	return 0;
//}

//写一个函数可以判断一个数是不是素数。
//#include <stdio.h>
//#include <math.h>


//1 为是素数
//0 为不是素数
//int is_prime(int n)
//{
//	int j = 0;
//
//	//for (j = 2; j <= i - 1; j++)
//	for (j = 2; j <= sqrt(n); j++)   // 减少遍历次数
//	{
//		if (n % j == 0)
//		{
//			return 0;
//		}	
//	}
//	return 1;
//}



//int main()
//{
//	int i = 0;
//	int count = 0;
//	for (i = 100; i <= 200; i++)
//	{
//		int flag = 1;//flag为1，表示素数
//		
//		if (is_prime(i))
//		{
//			printf("%d ", i);
//			count++;
//		}
//	}
//	printf("\ncount = %d\n", count);
//	return 0;
//}


// 写一个函数判断一年是不是闰年
//# include <stdio.h>
//int  year_function(int year)
//{
//	if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
//	{
//		return 1;
//	}
//	else
//	{
//		return 0;
//	}
//	
//}
//
//int main()
//{
//	int year = 0;
//	scanf("%d", &year);
//	if (year_function(year))
//	{
//		printf("%d是闰年", year);
//	}
//	else
//	{
//		printf("%d不是闰年", year);
//	}
//	return 0;
//	
//}


//2024.3.27


//写一个函数，实现一个整形有序数组的二分查找
//int binary_search(int arr[], int search_element, int size) // 数组传参实际上是传递数组首元素的地址，而不是整个数组
															 //形参 arr[]看上去是数组，本质是指针变量
//{														     // 所以在函数内部计算数组元素个数是有问题的
//	int left = 0;
//	int right = size - 1;
//	int sz = sizeof(arr) / sizeof(arr[0]);			   //错误
//
//	while (left <= right)
//	{
//		int mid = left + (right - left) / 2;
//		int mid = (left + right) / 2;
//		if (arr[mid] < search_element)
//		{
//			left = mid + 1;
//		}
//		else if(arr[mid] > search_element)
//		{
//			right = mid - 1;
//		}
//		else
//		{
//			return mid;
//		}
//	}
//	return -1;
//}
//
//#include <stdio.h>
//int main()
//{
//	int arr[20] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//
//	int k = 1;  //查找的元素
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	找到了，返回下标
//	找不到，返回-1
//	int ret = binary_search(arr, k, sz);
//	if (-1 == ret)
//	{
//		printf("找不到");
//	}
//	else
//	{
//		printf("找到了，下标是:%d\n", ret);
//	}
//	return 0;
//}

//布尔类型
//#include <stdio.h>
//#include <stdbool.h>
//#include <math.h>
//bool is_prime(int n)
//{
//	int j = 0;
//
//	//for (j = 2; j <= i - 1; j++)
//	for (j = 2; j <= sqrt(n); j++)   // 减少遍历次数
//	{
//		if (n % j == 0)
//		{
//			return false;
//		}	
//	}
//	return true;
//}
//
//int main()
//{
//	int i = 0;
//	for (i = 100; i <= 200; i++)
//	{
//		if ((is_prime(i)))
//			printf("%d ", i);
//	}
//	//printf("%d", sizeof(bool)); //bool类型为1个字节
//	return 0;
//}



//写一个函数，每调用一次这个函数，就会将 num 的值增加1
//void add_1(int* num)
//{
//	//int tmp = 0;
//	//tmp = *num + 1;
//	//*num = tmp;
//	(*num)++;
//}
//
//#include <stdio.h>
//int main()
//{
//	int num = 0;
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		add_1(&num);    //用指针传参来改变num值
//		printf("%d\n", num);
//	}
//	return 0;
//}


//以下2个不推荐的写法
//int ADD(int a, int b)
//{
//	printf("hehe\n"); //函数返回值是printf函数的返回值，为5
//}
//
//ADD(int x, int y) //函数没有返回类型，默认是范围int
//{
//	return x + y;
//}
//
//void test(void)   //明确说明test()函数不需要参数
//{
//	printf("hehe\n");
//
//}

//main函数其实是有3个参数
// 示例：./test.c -a -b
//参数argc表示的是传入参数的个数    3
//参数char* argv[],指针数组，每一个元素指向一个参数，
//如argv[0]：指向程序运行的全路径名，即./test.c
//argv[1]：指向执行程序名后的第一个字符串 ，表示真正传入的第一个参数，即 -a
//argv[2]：指向执行程序名后的第二个字符串 ，表示传入的第二个参数. 即 -b
//参数char* envp[],获得环境变量
//int main(int argc, char* argv[], char* envp[])
//{
//	return 0;
//}


//#include <stdio.h>
//#include <string.h>
//int main()
//{
//	char arr[20] = "hello";
//	int ret = strlen(strcat(arr, "bit"));  //函数的链式访问
//	printf("%d\n", ret);
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	printf("%d", printf("%d", printf("%d", 43)));  //4321
//	return 0;
//}


//2024.3.27晚上
//函数的声明和定义

//#include  <stdio.h>
//#include <stdlib.h>
//#include "add.h"
//#include "sub.h"

//int ADD(int x, int y);    //函数的声明


//导入静态库  (使用头文件和静态库lib打包给客户使用，而不给.c源文件给客户)
//#pragma comment(lib, "add.lib")


//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	int ret = ADD(a, b);
//	printf("%d\n", ret);
//
//	int ret2 = SUB(a, b);
//	printf("%d\n", ret2);
//	return 0;
//}

//函数的定义
//int ADD(int x, int y)
//{
//	return x + y;
//}



//2024.3.28
//函数递归

//接受一个整型值（无符号），按照顺序打印它的每一位。
//例如：
//输入：1234，输出 1 2 3 4

//%d 打印有符号的整数（正负数）
//%u 打印无符号整数

//int main()
//{
//	unsigned int num = 0;
//	scanf("%u", &num);
//	while (num)
//	{
//		printf("%d ", num % 10);
//		num = num / 10;
//	}
//	return 0;
//}

//递归实现
//void print(unsigned int n)
//{
//	if (n > 9)   //递归条件 不写这个条件会栈溢出
//	{
//		print(n / 10);
//
//	}
//	printf("%d ", n % 10);
//}

//print(1234) 4
//print(123) 3
//print(12) 2
//print(1) 1

//int main()
//{
//	unsigned int num = 0;
//	scanf("%u", &num);
//	print(num);
//	return 0;
//}


//编写函数不允许创建临时变量，求字符串的长度

//#include <stdio.h>
//int my_str(char str[])  //char chr[] 与char* str本质是一样的
//int my_strlen(char* str)
//{
//	int count = 0;
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//	return count;
//}

//递归求解, 不创建临时变量
//my_strlen("abc")
//1+my_strlen("bc")
//1+1+my_strlen("c")
//1+1+my_strlen("")
//1+1+1+0

//int my_strlen(char* str)
//{
//	if (*str != '\0')
//	{
//		return 1 + my_strlen(str + 1);
//
//	}
//	else
//	{
//		return 0;
//	}
//}


//int main()
//{
//	char arr[] = "abc"; //[a b c \0]
//	int ret = my_strlen(arr);
//
//	printf("%d\n", ret);
//	return 0;
//}


//求n的阶乘。（不考虑溢出）
//int fac(int n)
//{
//	if (n <= 1)
//	{
//		return 1;
//	}
//	else
//	{
//		return n * fac(n - 1);
//	}
//}
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = fac(n);
//	printf("ret = %d", ret);
//
//}

//求第n个斐波那契数
//斐波那契数列
//1 1 2 3 5 8 13 21 34 55 ...
//递归太耗时间
//int Fib(int n)
//{
//	if (n <= 2)
//		return 1;
//	else
//	{
//		return Fib(n - 1) + Fib(n - 2);
//	}
//}

//效率更高
//int Fib(int n)
//{
//	int a = 1;
//	int b = 1;
//	int c = 0;
//
//	while (n >= 3)
//	{
//		c = a + b;
//		a = b;
//		b = c;
//		n--;
//	}
//	return c;
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = Fib(n);
//	printf("Fib(%d) = %d\n", n, ret);
//	return 0;
//}

//乘法口诀表
//void func_1(int n)
//{
//	int i = 0;
//	int j = 0;
//	//打印n行
//	for (i = 1; i <= n; i++)
//	{
//		for (j = 1; j <= i; j++)
//		{	
//			//%-2d，2位左对齐，数的右边空两格(%2d，2位右对齐)
//			printf("%d*%d=%-2d ", i, j, i * j); 
//		}
//		printf("\n");
//	}
//		
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	func_1(n);
//	return 0;
//}

//2024.3.29

//编写程序数一下 1到 100 的所有整数中出现多少个数字9
//9 19 29 39 49 59 69 79 89 99
//90 91 92 93 94 95 96 97 98 99
//int main()
//{
//	int i = 0;
//	int count = 0;
//	for (i = 1; i <= 100; i++)
//	{
//		//判断个位是不是9
//		if (i % 10 == 9)
//		{
//			count++;
//		}
//		//判断十位是不是9
//		if (i / 10 == 9)
//		{
//			count++;
//		}
//	}
//	printf("count = %d\n", count);
//	return 0;
//}


//计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值，打印出结果
//分子为1
//分母为1~100

//int main()
//{
//	int i = 0;
//	double sum = 0.0;
//	int flag = 1;
//	for (i = 1; i <= 100; i++)
//	{
//		sum = sum + flag*(1.0 / i);
//		flag = -flag;
//	}
//	printf("sum = %lf\n", sum);
//	return 0;
//}



//求10 个整数中最大值
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//
//	//找出最大值
//	int max = arr[0];
//	int i = 0;
//	for (i = 1; i < 10; i++)
//	{
//		if (arr[i] > max)
//		{
//			max = arr[i];
//		}
//
//	}
//	printf("max = %d\n", max);
//	return 0;
//}


//void test(int arr[])
//{
//	arr[0] = 3;  // arr[0] -> *(arr + 0)
//	arr[1] = 4;	 // arr[1] -> *(arr + 1)
//
//}
//int main()
//{
//	int arr[2] = { 0 };
//	test(arr);
//	printf("%d, %d", arr[0], arr[1]);
//	return 0;
//
//}


//int main()
//{
//	//在C99标准之前，数组大小必须是常量或常量表达式
//	//在C99标准之后，数组大小可以是变量，为了支持变长数组
//	int n = 10;
//	int arr[n]; //不能初始化
//
//	//不完全初始化，剩余的元素默认初始化为0
//	int arr[10] = { 1, 2, 3 };
//
//	//存储内容：a b c 0 0 0 0 0 0 0 
//	char ch1[10] = { 'a', 'b', 'c' };
//
//	//存储内容：a b c \0 0 0 0 0 0 0
//	char ch2[10] = "abc";
//
//
//	return 0;
//}


//一维数组
//int main()
//{
//	//数组在内存中是连续存储的
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	//printf("%d\n", arr[7]);
//	//printf("%d", *(arr + 7));//arr[7] 和 *(arr + 7)是一样的
//
//	int sz = sizeof(arr) / sizeof(arr[0]);  //计算arr数组的大小
//	/*for (int i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}*/
//	for (int i = 0; i < sz; i++)
//	{
//		printf("&arr[%d] = %p\n", i, &arr[i]);
//	}
//	return 0;
//}


//二维数组
//1 2 3 4
//2 3 4 5
//3 4 5 6

//int main()
//{	
//	int arr[] = { 1, 2, 3, 4, 5 };
//	int arr1[3][4] = { 1, 2 , 3, 4, 5, 6, 7, 8 };
//	int arr2[3][4] = { {1, 2, 3, 4}, {2, 3} };
//	int arr3[][4] = { {1, 2, 3, 4}, {2, 3} };
//
//	int arr[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			printf("arr[%d][%d] = %d\n", i, j, arr[i][j]);
//		}
//	}
//	return 0;
//}

//int main()
//{
//	int arr[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
//	int i = 0;
//
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			//二维数组在内存也是连续存储，如arr[3][4]和arr[12]在内存中存储方式是一样的
//			printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
//		}
//	}
//	return 0;
//}


//数组越界
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6 };  //0~5
//	int i = 0;
//	//int sz = sizeof(arr) / sizeof(arr[0]);
//
//	for (i = 0; i < 10; i++)  //0~10
//	{
//		printf("%d\n", arr[i]); //越界后打印的值是未知的
//	}
//	return 0;
//}

//冒泡排序:两个相邻的元素进行比较，一趟冒泡排序让一个数据来到它最终应该出现的位置
//数组传参的时候，形参有2种写法
//1.数组
//2.指针

//形参是指针的形式
//void bubble_sort(int* arr, int sz){}


//形参是数组的形式
//void bubble_sort(int arr[], int sz)
//{
//	//趟数  如，10个数需要9趟冒泡
//	//int sz = sizeof(arr) / sizeof(arr[0]);  //不能把算数组大小放在函数里面算，因为算出来的结果是错误的
//	int i = 0;
//	for (i = 0; i < sz - 1; i++)
//	{
//		//一趟冒泡排序
//		int j = 0;
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			if (arr[j] > arr[j + 1])
//			{
//				//交换
//				int tmp = arr[j];
//				arr[j] = arr[j + 1];
//				arr[j + 1] = tmp;
//			}
//		}
//	}
//}

//int main()
//{
//	int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
//	//冒泡排序算法，实现对数组进行升序排序
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	bubble_sort(arr, sz);  //数组名本质是数组首元素的地址
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	
//	return 0;
//}


//一维数组
//数组名确实能表示首元素的地址
//但是有2个例外:
//1.sizeof(数组名)，这里的数组名表示整个数组，计算的是整个数组的大小，单位是字节
//2.&数组名，这里的数组名表示整个数组，取出的是整个数组的地址

//int main()
//{
//	int arr[10] = {0};
//	printf("%p\n", arr); //数组首元素的地址   007FFE90
//	printf("%p\n", arr + 1); //				  007FFE94 (隔了4个字节)
//	printf("---------------------------\n");
//
//	printf("%p\n", &arr[0]); //数组首元素的地址  007FFE90
//	printf("%p\n", &arr[0]+1);//				 007FFE94 (隔了4个字节)
//	printf("---------------------------\n");
//
//	printf("%p\n", &arr); //数组的地址   007FFE90
//	printf("%p\n", &arr + 1);//			 007FFEB8 (隔了40个字节)
//
//	//int n = sizeof(arr);     //n = 40字节
//	//printf("%d\n", n);
//}


//二维数组的数组名的理解
//int main()
//{
//	int arr[3][4] = { 0 };
//	printf("%d\n", sizeof(arr) / sizeof(arr[0]));       //计算二维数组的行数
//	printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0])); //计算二维数组的列数
//	printf("---------------------------\n");
//
//
//	int sz = sizeof(arr);   //48字节
//	printf("%d\n", sz);
//
//	printf("---------------------------\n");
//	printf("%p\n", arr);    //二维数组的数组名也表示数组首元素的地址（arr[0]的地址）012FF9F4
//	printf("%p\n", arr[0]); //012FF9F4
//
//	printf("%p\n", arr+1);    //arr[1]首地址  012FFA04
//	printf("%p\n", arr[1]);   //012FFA04
//	printf("---------------------------\n");
//
//	printf("%p\n", &arr);		//012FF9F4
//	printf("%p\n", &arr + 1);	//012FFA24    (隔了48个字节)
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 1, 2, 3, 4, 5 };
//	printf("%p\n", arr);
//	printf("%p\n", &arr[0]);
//	printf("%d\n", *arr);
//	return 0;
//
//}



//2024.3.31
//字符串逆序（递归实现）
//char arr[] = "abcdef";
//逆序之后数组的内容变成：fedcba


//非递归，使用下标更改数值
//void reverse(char arr[])
//{
//	int left = 0;
//	//int right = sz - 2;
//	int right = strlen(arr) - 1;
//	while (left < right)
//	{
//		char tmp = arr[left];
//		arr[left] = arr[right];
//		arr[right] = tmp;
//		left++;
//		right--;
//	}
//}

//递归写法：方法一
//int  my_strlen(char* str)
//{
//	int count = 0;
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//	return count;
//}
//
//void reverse(char* str)
//{
//	char tmp = *str;               //第一个字符放进临时变量
//	int len = my_strlen(str);
//	*str = *(str + len - 1);
//	*(str + len - 1) = '\0';      //'\0'作为最后一个字符
//	if (my_strlen(str + 1) >= 2)  //当除了第一个字符和最后一个字符的中间字符串的字符个数超过2时，递归
//	{
//		reverse(str + 1);
//	}
//	*(str + len - 1) = tmp;      //把临时变量放到字符串的最后一个位置
//}


//递归写法：方法2
//void reverse(char arr[], int left, int right)
//{
//	char tmp = arr[left];
//	arr[left] = arr[right];
//	arr[right] = tmp;
//	if (left < right)
//	{
//		reverse(arr, left + 1, right - 1);
//	}
//}


//int main()
//{
//	char arr[] = "abcdef";    //[a b c d e f \0]
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int len = my_strlen(arr);
//	//reverse(arr);   //方法一
//	reverse(arr, 0, (len - 1));   //方法二
//	printf("%s\n", arr);
//	
//	//printf("%d\n", strlen(arr));
//	return 0;
//}



//写一个递归函数DigitSum(n)，输入一个非负整数，返回组成它的数字之和
//例如，调用DigitSum(1729)，则应该返回1 + 7 + 2 + 9，它的和是19
//输入：1729，输出：19 
//DitgieSum(1234)
//DitgieSum(123) + 4
//DitgieSum(12) + 4 + 3
//DitgieSum(1) + 2 + 4 + 3

//int DigitSum(unsigned int n)
//{
//	if (n > 9)
//	{
//		return DigitSum(n / 10) + n % 10;
//	}
//	else
//	{
//		return n;
//	}
//}
//
//
//int main()
//{
//	unsigned int n = 0;
//	scanf("%u", &n);
//	int ret = DigitSum(n);
//	printf("%d", ret);
//	return 0;
//}

//编写一个函数实现n的k次方，使用递归实现
//k > 0, pow(n, k) -> n * pow(n, k-1)
//k < 0, 1/(pow(n, -k))

//double my_pow(int n, int k)
//{
//	if (k > 0)
//	{
//		return n * my_pow(n, k - 1);
//	}
//	else if (k < 0)
//	{
//		 
//		return 1.0 / my_pow(n, -k);
//	}
//	else
//	{
//		return 1;
//	}
//}
//
//int main()
//{
//	int n = 0;
//	int k = 0;
//	scanf("%d %d", &n, &k);
//	double ret = my_pow(n, k);
//	printf("%lf\n", ret);
//	return 0;
//}


//将数组A中的内容和数组B中的内容进行交换。（数组一样大）
//int main()
//{
//	int arr1[] = { 1, 2, 3, 4, 5, 6, 7 };
//	int arr2[] = { 8, 9, 10, 11, 12, 13, 14 };
//	int i = 0;
//	int j = 0;
//	int z = 0;
//	int sz = sizeof(arr1) / sizeof(arr1[0]);
//
//	for (i = 0; i < sz; i++)
//	{
//		int tmp = arr1[i];
//		arr1[i] = arr2[i];
//		arr2[i] = tmp;
//	}
//
//	for (j = 0; j < sz; j++)
//	{
//		printf("arr1[%d] = %d\n", j, arr1[j]);
//	}
//	for (z = 0; z < sz; z++)
//	{
//		printf("arr2[%d] = %d\n", z, arr2[z]);
//	}
//	return 0;
//}


//创建一个整形数组，完成对数组的操作
//实现函数init() 初始化数组为全0
//实现print()  打印数组的每个元素
//实现reverse()  函数完成数组元素的逆置。
//要求：自己设计以上函数的参数，返回值。


//void init(int arr[], int size)
//{
//	int i = 0;
//	for (i = 0; i < size; i++)
//	{
//		arr[i] = 0;
//	}
//}
//
//void print(int arr[], int size)
//{
//	int i = 0;
//	for (i = 0; i < size; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	printf("\n");
//}
//
//void reverse(int arr[], int size)
//{
//	int left = 0;
//	int right = size - 1;
//	int i = 0;
//	while(left < right)
//	{
//		int tmp = arr[left];
//		arr[left] = arr[right];
//		arr[right] = tmp;
//		left++;
//		right--;
//	}
//
//}
//
//int main()
//{
//	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	reverse(arr, sz);
//	print(arr, sz);
//	init(arr, sz);
//	print(arr, sz);
//	return 0;
//}


//操作符
//% 取模操作符的两端必须是整数
//整数的二进制表示有3种：原码、反码、补码

//正的整数的原码、反码、补码相同
//负的整数的原码、反码、补码要计算

//7
//原码：0000 0000 0000 0000 0000 0000 0000 0111
//反码：0000 0000 0000 0000 0000 0000 0000 0111
//补码：0000 0000 0000 0000 0000 0000 0000 0111

//-7
//原码：1000 0000 0000 0000 0000 0000 0000 0111
//反码：1111 1111 1111 1111 1111 1111 1111 1000（符号位不变，其他按位取反）
//补码：1111 1111 1111 1111 1111 1111 1111 1001（反码+1）
//整数在内存中存储的是补码


//左移
//int main()
//{	
//	//移位只针对整数，浮点数没有这概念
//	int a = 7;
//	int b = a << 1; 
//	printf("a = %d\n", a); //7
//	printf("b = %d\n", b); //14
//
//	int c = -7;
//	int d = c << 1;
//	printf("c = %d\n", c); //-7
//	printf("d = %d\n", d); //-14
//
//	return 0;
//}

//右移2种
//算术移位：右边丢弃，左边补原符号位
//逻辑移位：右边丢弃，左边补0

//int main()
//{
//	int a = -7;
//	int b = a >> 1;
//	printf("a = %d\n", a);  //-7
//	printf("b = %d\n", b);  //-4 (vs编译器采用的是算术右移)
//	return 0;
//}

// & - 按位与
// | - 按位或
// ^ - 按位异或   相异为1，相同为0

//int main()
//{
//	int a = 3;
//	int b = -5;
//	int c = a & b;   //a 和 b 的二进制补码来进行&运算
//	int c = a | b;
//	int c = a ^ b;
//	printf("c = %d\n", c);   //3
//	return 0;
//
//}


//不能创建临时变量（第三个变量），实现两个数的交换
//使用异或: 0 ^ a = a、 a ^ a = 0  、支持交换律

//int main()
//{
//	int a = 3;
//	int b = 5;
//
//	printf("交换前：a = %d b = %d\n", a, b);
//	//这种方法解决不了溢出问题，如果a和b是足够大的数的话
//	//  a = a + b;
//	//	b = a - b;
//	//	a = a - b;
//
//	//异或的方法
//	a = a ^ b;  // a = 3^5
//	b = a ^ b;  //b = 3^5^5 = 3
//	a = a ^ b;  //a = 3^5^3 = 5
//	printf("交换后：a = %d b = %d\n", a, b);
//	return 0;
//
//}




// 2024.4.1
//求一个整数存储在内存中的二进制中1的个数
//求补码的二进制中的1的个数、
// int a = 3
// a & 1
// 0000 0000 0000 0000 0000 0000 0000 0011
// 0000 0000 0000 0000 0000 0000 0000 0001

//int main()
//{
//	//1000 0000 0000 0000 0000 0000 0000 0001 (-1原码)
//	//1111 1111 1111 1111 1111 1111 1111 1110 (-1反码)
//	//1111 1111 1111 1111 1111 1111 1111 1111 (-1补码)
//	int num = -1;     
//	int count = 0;
//	int i = 0;
//	for (i = 0; i < 32; i++)
//	{
//		if (num & (1 << i))
//		{
//			count++;
//		}
//		
//	}
//	printf("%d 的二进制1的个数为 %d", num, count);  // 32
//	return 0;
//}

//sizeof是操作符，不是函数
//int main()
//{
//	int a = 10;
//	printf("%d\n", sizeof int); //error
//	printf("%d\n", sizeof a);   //ok
//	return 0;
//}

//int main()
//{
//	int a = 0;
//	// ~ 二进制的按位取反
//	// 0000 0000 0000 0000 0000 0000 0000 0000   补码
//	// 1111 1111 1111 1111 1111 1111 1111 1111   ~a
//	// 1111 1111 1111 1111 1111 1111 1111 1110   反码
//	// 1000 0000 0000 0000 0000 0000 0000 0001   原码（-1）
//
//	printf("%d\n", ~a);   //按位取反，符号位也要去反
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int* p = &a;
//	*p = 20;
//	printf("%d\n", a);
//	return 0;
//}

//int main()
//{
//	int a = (int)3.14;
//	printf("%d", a);   // 3
//	return 0;
//}


//#include <stdio.h>
//void test1(int arr[])
//{
//	printf("%d\n", sizeof(arr));//(2)  4或8字节
//}
//
//void test2(char ch[])
//{
//	printf("%d\n", sizeof(ch));//(4)   4或8字节
//}
//
//int main()
//{
//	int arr[10] = { 0 };
//	char ch[10] = { 0 };
//	printf("%d\n", sizeof(arr));//(1)    40字节
//	printf("%d\n", sizeof(ch));//(3)     10字节
//	test1(arr);
//	test2(ch);
//	return 0;
//}

//int main()
//{
//	if (3 == 5)
//	{
//
//	}
//	//error，应使用strcmp()
//	if ("abc" == "abcdefg") //这样写是在比较2个字符串首字符的地址
//	{
//
//	}
//}



//逻辑与、逻辑或(只关注真假：0或1)
//int main()
//{
//	int a = 3;
//	int b = 0;
//	int c = a && b; 
//	int d = a || b;
//	printf("%d\n", c);
//	printf("%d\n", d);
//	return 0;
//}



//&& 左边为假，右边就不计算了
//|| 左边为真，右边就不计算了

//#include <stdio.h>
//int main()
//{
//	int i = 0, a = 0, b = 2, c = 3, d = 4;
//	// a=0 ,整个结果（i）直接为0，则++b、d++都不需要算了，b还是2，d还是4
//	i = a++ && ++b && d++;  
//	
//	int i = 0, a = 1, b = 2, c = 3, d = 4;
//	// a = 1,整个结果(i)直接为1， 则++b、d++都不需要算了，b还是2，d还是4
//	i = a++||++b||d++;  
//	printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d); //1 2 3 4
//	return 0;
//}


//int main()
//{
//	int a = 1;
//	int b = 2;
//	int c = (a > b, a = b + 10, a, b = a + 1);  //逗号表达式，结果取最后一个表达式的结果
//	printf("%d\n", c);
//}


//int main()
//{
//	int arr[10] = { 0 };
//	arr[7] = 8;
//
//	//深刻理解操作符
//	//ok，访问元素，验证了[]是操作符，如2 + 3 = 3 + 2；arr[7] = 7[arr]
//	7[arr] = 9;  
//	return 0;
//}


//struct Stu
//{
//	char name[20];
//	int age;
//	double score;
//};
//
//void set_stu(struct Stu* ss)
//{
//	//结构体对象.成员
//	//strcpy((*ss).name, "张三");
//	//(*ss).age = 20;
//	//(*ss).score = 20.0;
//
//	//结构体指针->成员
//	strcpy(ss->name, "张三");
//	ss->age = 20;
//	ss->score = 20.0;
//}
//
//void print_stu(struct Stu* ss)
//{
//	//结构体对象.成员
//	printf("%s %d %lf\n", (*ss).name, (*ss).age, (*ss).score);
//
//	//结构体指针->成员
//	printf("%s %d %lf", ss->name, ss->age, ss->score);
//}
//
//int main()
//{
//	struct Stu s = { 0 };
//	//若传值s过去，函数内部又要拷贝一份数据，造成空间浪费，传&s就没有这个问题
//	set_stu(&s);
//	print_stu(&s);
//	return 0;
//}


//int main()
//{
//	// 00000000 00000000 00000000 00000101    5
//	// 00000101 -a
//	char a = 5;
//
//	// 00000000 00000000 00000000 01111110    126
//	// 01111110 -b
//	char b = 126;
//	char c = a + b;
//	// 00000000 00000000 00000000 00000101  ->a
//	// 00000000 00000000 00000000 01111110  ->b
//	// 00000000 00000000 00000000 10000011 ->a+b
//	// 10000011  ->c  (高位为1，整型提升，全部补1)
//	// 11111111 11111111 11111111 10000011 ->补码
//	// 11111111 11111111 11111111 10000010 ->反码
//	// 10000000 00000000 00000000 01111101 -> 原码 (-125)
//
//	printf("%d\n", c); // -125
//	return 0;
//}


//int main()
//{
//	char a = 0xb6;    // 1011 0110  (高位补1，变负数)
//	short b = 0xb600; // 1011 0110 0000 0000 (高位补1，变负数)
//	int c = 0xb6000000;
//
//	// a,b整形提升之后,变成了负数
//	if (a == 0xb6)
//		printf("a");
//	if (b == 0xb600)
//		printf("b");
//	if (c == 0xb6000000)
//		printf("c");      //打印c
//	return 0;
//}


//int main()
//{
//	char c = 1;
//	printf("%u\n", sizeof(c));   // 1
//	printf("%u\n", sizeof(+c));  // 4 字符型参与运算，成为表达式则需要整型提升
//	printf("%u\n", sizeof(-c));  // 4 字符型参与运算，成为表达式则需要整型提升
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int i = 1;
//	int ret = (++i) + (++i) + (++i);
//	printf("%d\n", ret);
//	printf("%d\n", i);
//	return 0;
//}


// 小乐乐上课需要走n阶台阶，每次可以选择走一阶或走两阶，他一共有多少走法

//int fib(int n)
//{
//	if (n <= 2)
//	{
//		return 2;
//	}
//	else
//	{
//		return fib(n - 1) + fib(n - 2);
//	}
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//
//	int m = fib(n);
//	printf("%d\n", m);
//	return 0;
//}

//删除数组中指定元素，并打印删除后的数组
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int arr[50] = {0};
//
//	int i = 0;
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//	}
//	int del = 0;
//	scanf("%d", &del);
//	int j = 0;  //存放不删除数据的下标
//	for (i = 0; i < n; i++)
//	{
//		if (arr[i] != del)
//		{
//			arr[j++] = arr[i];
//		}
//	}
//	//输出
//	for (i = 0; i < j; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}


// 最高分和最低分之差
// 方法一
//int main()
//{
//	int arr[10] = { 0 };
//	int i = 0;
//	int n = 0;
//	scanf("%d", &n);
//
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//	}
//	int max = arr[0];
//	for (i = 0; i < n; i++)
//	{
//		if (arr[i] > max)
//		{
//			max = arr[i];
//		}
//	}
//
//	int min = arr[0];
//	for (i = 0; i < n; i++)
//	{
//		if (arr[i] < min)
//		{
//			min = arr[i];
//		}
//	}
//	printf("%d\n", max - min);
//	return 0;
//}

//方法二
//int main()
//{
//	int arr[10] = { 0 };
//	int i = 0;
//	int n = 0;
//	int max = 0;
//	int min = 100;
//	scanf("%d", &n);
//
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//		if (arr[i] > max)
//		{
//			max = arr[i];
//		}
//		if (arr[i] < min)
//		{
//			min = arr[i];
//		}
//	}
//	printf("%d\n", max - min);
//	return 0;
//}



//2024.4.3
//字母大小写转换
//int main()
//{	
//	char ch = 0;
//	while (scanf("%c", &ch) == 1) //scanf成功接收输入，会返回读取元素的个数，否则返回EOF
//	{
//		if (ch >= 'a' && ch <= 'z')  //if (islower(ch))  判断是否是小写，是则返回1
//		{
//			printf("%c", ch - 32);   // printf("%c", toupper(ch));    转换成大写
//		}
//		else if (ch >= 'A' && ch <= 'Z') //if (isupper(ch))
//		{
//			printf("%c", ch + 32);    // printf("%c", tolower(ch));
//		}
//	}
//	return 0;
//}

//判断是不是字母
//int main()
//{
//	char ch = 0;
//	// %c的前面加空格：跳过下一个字符之前的所有空白字符
//	while (scanf(" %c", &ch) == 1)
//	{
//		if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))  //   if (isalpha(ch))
//		{
//			printf("%c is alphabet.\n", ch);
//		}
//		else
//			printf("%c is not a alphabet.\n", ch);
//		//getchar(); // 读取一个字符，把scanf后的 \n 给读取掉（清除掉）
//	}
//	return 0;
//}


//输入三个数，找出最大的数
//int main()
//{
//	int i = 0;
//	int max = 0;
//	int score = 0;
//
//	for (i = 0; i < 3; i++)
//	{
//		scanf("%d", &score);
//		if (max < score)
//		{
//			max = score;
//		}
//	}
//	printf("%d", max);
//	return 0;
//}


//变种水仙花数(从中间拆分成两个数，若所有拆分后的乘积之和等于自身，则是一个变种水仙花数)
// 655 = 6 * 55 + 65 * 5
// 1461 = 1 * 461 + 14 * 61 + 146 * 1

//int main()
//{
//	int i = 0;
//	for (i = 10000; i <= 99999; i++)
//	{
//		//判断i是否为变种水仙花数
//		int sum = 0;
//		int j = 0;
//		for (j = 1; j <= 4; j++)
//		{
//			int k = (int)pow(10, j);   // 10的j次方
//			sum += (i / k) * (i % k); 
//		}
//		if (sum == i)
//		{
//			printf("%d\n", i);
//		}
//	}
//	return 0;
//}


//指针和指针类型
//int main()
//{
//	char* pc = NULL;
//	short* ps = NULL;
//	int* pi = NULL;
//	double* pd = NULL;
//	
//	printf("%zu\n", sizeof(pc));
//	printf("%zu\n", sizeof(ps));
//	printf("%zu\n", sizeof(pi));
//	printf("%zu\n", sizeof(pd));
//	return 0;
//
//}

//指针类型的意义
//int main()
//{
//	int a = 0x11223344;
//	char* pc = (char*)&a;  //int* 强转成 char*
//	*pc = 0;
//
//	//结论1:
//	//指针类型决定了指针在解引用时可以访问几个字节
//	//int* ,解引用访问4个字节
//	//char* ,解引用访问1个字节
//	//以此类推
//	return 0;
//
//}

//int main()
//{
//	int a = 0x1122334;
//	int* pa = &a;
//	char* pc = (char*)&a;
//
//	printf("pa = %p\n", pa);
//	printf("pa+1 = %p\n", pa+1);
//
//	printf("pc = %p\n", pc);
//	printf("pc+1 = %p\n", pc + 1);
//	//结论2：
//	//指针的类型决定了指针+-1
//	return 0;
//}

//int main()
//{
//	int a = 0;
//	int* pi = &a;    //pi解引用访问4个字节，pi+1也是跳过4个字节
//	float* pf = &a;  //pf解引用访问4个字节，pf+1也是跳过4个字节
//
//	// int* 和float* 是不是可以通用？肯定不能
//	//他们在内存的存放数值的方式是不一样的
//	*pi = 100;  
//	*pf = 100.0;
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 0 };
//	int* p = arr; //&arr[0]
//
//	int i = 0;
//	for (i = 0; i <= 10; i++)  //数组越界访问，产生野指针
//	{
//		*p = i;
//		p++;
//	}
//	return 0;
//}


//int* test()
//{
//	int a = 10;
//	return &a;
//
//}


//int main()
//{
//	int* p = test(); //野指针，局部变量a出了函数体后就销毁了，返回a的地址，该地址指向的内容是未知的
//	printf("Hello");
//	printf("%d\n", *p);//打印出来的就不是10了，因为栈帧被printf函数覆盖了；若没覆盖，则还是10
//
//	int* p2 = NULL;
//	*p2 = 100;//error 0指针的内容是无法访问的
//
//
//
//	int* p3 = NULL;
//
//	if (p3 != NULL)
//	{
//		*p3 = 100;//ok
//	}
//	return 0;
//}


//#define N_VALUES 5
//float values[N_VALUES];
//float* vp;
////指针+-整数；指针的关系运算
//for (vp = &values[0]; vp < &values[N_VALUES];)
//{
//	*vp++ = 0;   // 先*vp(数值)赋值为0.然后指针vp++
//}


//使用指针来初始化数组元素
//int main()
//{
//	int arr[10] = { 0 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	int* p = arr;
//	for (int i = 0; i < sz; i++)
//	{
//		//*p++ = 1;  // *p(数值)=1.然后指针p++
//		//*(p+i) = 1;
//		*p = 1;
//		p++;
//
//	}
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%d\n", arr[i]);
//
//	}
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 0 };
//	printf("%d", &arr[9] - &arr[0]); // 9 指向同一块空间的2个指针才能相减（才有意义）
//
//	char ch[5] = { 0 };
//	printf("%d\n", &ch[0] - &arr[0]);//error 没意义
//	return 0;
//}


//指针-指针来求字符串长度
//int my_strlen(char* str)
//{
//	char* start = str;
//	while (*str != '\0')
//	{
//		str++;
//	}
//	return (str - start);
//}

//int main()
//{
//	char ch[] = "abcdefg";
//	int len = my_strlen(ch);
//	printf("%d\n", len);
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 0 };
//	int* p = arr;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));   //arr[i] == *(arr + i)
//	}
//	return 0;
//}





//二级指针
//二级指针变量是用来存放一级指针变量的地址
//int main()
//{
//	int a = 10;
//	int* pa = &a;    //pa是一个指针变量，一级指针变量  int* pa：  pa是指向int类型的指针
//	int** ppa = &pa;  //ppa是一个二级指针变量          int** ppa: ppa是指向int* 类型的指针
//	**ppa = 20;
//	printf("%d\n", a);
//	return 0;
//
//}



//指针数组：存放指针的数组

//int main()
//{
//	int a = 10;
//	int b = 20;
//	int c = 30;
//
//	int arr[10];
//
//	int* pa = &a;
//	int* pb = &b;
//	int* pc = &c;
//
//	//指针数组
//	int* parr[10] = { &a, &b, &c };
//
//	for (int i = 0; i < 3; i++)
//	{
//		printf("%d\n", *(parr[i]));
//	}
//	return 0;
//}



//使用指针数组模拟二维数组的效果
//int main()
//{
//	int arr1[4] = { 1, 2, 3, 4 };
//	int arr2[4] = { 2, 3, 4, 5 };
//	int arr3[4] = { 4, 5, 6, 7 };
//
//	int* parr[3] = { arr1, arr2, arr3 };
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			//arr1[j]、arr2[j]、arr3[j]  arr[i] == *(arr + i)，[]相当于可视为解引用
//			printf("%d ", parr[i][j]); 
//		}
//		printf("\n");
//	}
//	return 0;
//
//}

//2024.4.6
//结构体

//struct Peo
//{
//	char name[20];
//	char tele[120];
//	char sex[5];
//	int high;
//};p1, p2;  //p1和p2是使用struct Peo结构类型创建的2个变量，并且是全局变量
////一般情况下，少用或不要用全局变量
//
//
//struct Stu
//{
//	struct Peo p;
//	int num;
//	float f;
//};
//
//void print1(struct Peo p)
//{
//	printf("%s %s %s %d\n", p.name, p.tele, p.sex, p.high);			//结构体变量.成员变量
//
//}
//
//void print2(struct Peo* p)
//{
//	printf("%s %s %s %d\n", p->name, p->tele, p->sex, p->high);		//结构体指针->成员变量
//}
//
//
//int main()
//{
//	struct Peo p3 = { "张三", "122323323278", "男", 181 };   //结构体变量的创建
//	struct Stu st = { {"李四", "144533465534", "女",166}, 100, 3.14f };
//	printf("%s %s %s %d\n", p3.name, p3.tele, p3.sex, p3.high);
//	printf("%s %s %s %d %d %f\n", st.p.name, st.p.tele, st.p.sex, st.p.high, st.num, st.f);
//	print1(p3);     //结构体变量传参   形参是实参的一个临时拷贝，时间和空间都浪费巨大
//	print2(&p3);    //结构体指针传参
//	return 0;
//
//}

//【题目名称】
//
//统计二进制中1的个数
//
//【题目内容】
//
//写一个函数返回参数二进制中 1 的个数。
//
//比如： 15    0000 1111    4 个 1


//第一种写法：
//int count_num_of_1(unsigned int num)
//{
//	int count = 0;
//	while (num)
//	{
//		if (num % 2 == 1)
//		{
//			count++;
//		}
//		num /= 2;
//	}
//	return	count;
//}

//第二种写法
//int count_num_of_1(int num)
//{
//	int i = 0;
//	int count = 0;
//	for (i = 0; i < 32; i++)
//	{
//		if ((num & (1 << i)) != 0)
//			count++;
//	}
//	return count;
//}

//第三种方法
// n = 15
// n = n & (n-1)   每执行一次，n最右边都会少一个1
// 1111 n
// 1110 n-1
// 1110 n
// 1101 n-1
// 1100 n
// 1011 n-1
// 1000 n
// 0111 n-1
// 0000 n 

int count_num_of_1(int num)
{
	int count = 0;
	while (num)
	{
		num = num & (num - 1);
		count++;
	}
	return count;
}


//如果要判断一个数是不是2的n次方
//2^1   10
//2^2   100
//2^3   1000

//if ((n & (n - 1)) == 0)
//{
//
//}

//int main()
//{
//	int num = 0;
//	scanf("%d", &num);
//	int n = count_num_of_1(num);
//	printf("%d\n", n);
//	return 0;
//}



//【题目名称】
//
//求两个数二进制中不同位的个数
//
//【题目内容】
//
//编程实现：两个int（32位）整数m和n的二进制表达中，有多少个位(bit)不同？
//
//输入例子 :
//
//1999 2299
//
//输出例子 : 7

//int count_diff_bit(int num1, int num2)
//{
//	int count = 0;
//	int i = 0;
//	for (i = 0; i < 32; i++)
//	{
//		if (((num1 >> i) & 1) != ((num2 >> i) & 1))
//		{
//			count++;
//		}
//	}
//	return count;
//}

//int count_diff_bit(int m, int n)
//{
//	int count = 0;
//	//^异或操作符
//	//相同为0，相异为1
//	int ret = m ^ n;
//	//统计ret中二进制位有几个1
//	while (ret)
//	{
//		ret = ret & (ret - 1);
//		count++;
//	}
//	return count;
//}
//int main()
//{
//	int m = 0;
//	int n = 0;
//	scanf("%d %d", &m, &n);
//	int ret = count_diff_bit(m, n);
//	printf("%d\n", ret);
//	return 0;
//}

//【题目名称】
//
//打印整数二进制的奇数位和偶数位
//
//【题目内容】
//
//获取一个整数二进制序列中所有的偶数位和奇数位，分别打印出二进制序列
//10
//00000000 00000000 00000000 00001010

//int main()
//{
//	int i = 0;
//	int num = 0;
//	scanf("%d", &num);
//
//	//获取奇数位的数字
//	for (i = 30; i >= 0; i -= 2)
//	{
//		printf("%d ", (num >> i) & 1);
//
//	}
//	printf("\n");
//
//	//获取偶数位的数字
//	for (i = 31; i >= 1; i -= 2)
//	{
//		printf("%d ", (num >> i) & 1);
//
//	}
//	return 0;
//
//}


//全局变量、静态变量存放在静态区
//全局变量，静态变量不初始化时，默认初始化为0
//局部变量，不初始化，则初始化随机值

//int i;
//int main()
//{
//	i--;//-1
//	//sizeof计算返回结果是size_t类型，无符号整型
//	if (i > sizeof(i))   //都转换成无符号整型数,-1的补码是32位全是1，转成unsigned int则是一个很大的正数，所以 >4
//	{
//		printf(">\n");
//	}
//	else
//	{
//		printf("<\n");
//	}
//	return 0;
//}



// 2024.4.7

//X形图案
//输入描述:
//多组输入，一个整数(2~20)，表示输出的行数，也表示组成“X“的反斜线和正斜线的长度。
//输出描述 :
//针对每行输入，输出用“*”组成的X形图案,
//可看成一个矩形，里面包含*和空格
//int main()
//{
//	int n = 0;
//	while (scanf("%d", &n) == 1)
//	{
//		int i = 0;
//		int j = 0;
//		for (i = 0; i < n; i++)
//		{
//			for (j = 0; j < n; j++)
//			{
//				if (i == j)
//					printf("*");
//				else if (i + j == n - 1)
//					printf("*");
//				else
//					printf(" ");
//			}
//			printf("\n");
//		}
//	}
//	return 0;
//}


//KiKi想获得某年某月有多少天，请帮他编程实现。输入年份和月份，计算这一年这个月有多少天。
//输入描述 :
//多组输入，一行有两个整数，分别表示年份和月份，用空格分隔.
//输出描述 :
//针对每组输入，输出为一行，一个整数，表示这一年这个月有多少天。

//输入:2008 2
//输出 : 29


//int is_leap_year(int y)
//{
//	return (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)); // 逻辑操作符，如果为真，返回1；如果为假，返回0
//}
//int main()
//{
//	int y = 0;
//	int m = 0;
//	int d = 0;
//	int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//	//                   1  2   3    4   5   6  7    8  9   10  11  12月
//	while (scanf("%d %d", &y, &m) == 2)
//	{
//		int d = days[m];
//		if ((is_leap_year(y) == 1) && (m == 2))  //闰年的2月 要+1天
//		{
//			d++;
//		}
//		printf("%d\n", d);
//	}
//	return 0;
//}



//实用的调试技巧
//F9 打断点、取消断点
//
//int main()
//{
//	int arr[10] = { 0 };
//	int i = 0;
//	int a = 1;
//	int b = 2;
//	int c = 9;
//	for (i = 0; i < 10; i++)
//	{
//		arr[i] = i;
//	}
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}


//void test(int a[])
//{
//	//
//}

//int main()
//{
//	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	test(arr);
//	char arr1[] = "abcdefb";
//
//	return 0;
//}

//void test2()
//{
//	printf("Hello,world");
//}
//
//void test1()
//{
//	test2();
//}
//
//void test()
//{
//	test1();
//}
//
//int main()
//{
//	test();
//	return 0;
//}



//int main()
//{
//	int a = 10;
//	int b = 20;
//	int c = a + b;
//	return 0;
//}

//求 1！+2！+3！ ...+ n!
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int i = 0;
//	int j = 0;
//	int ret = 1;
//	int sum = 0;
//	for (j = 1; j <= n; j++)
//	{
//		ret = 1;
//		for (i = 1; i <= j; i++)
//		{
//			ret *= i;
//		}
//		sum += ret;
//	}
//	printf("%d\n", sum);
//	return 0;
//}

//1.栈区内存使用习惯：先使用高地址处的空间，再使用低地址处的空间
//2.数组随着下标的增长地址是由低到高变化的
//3.如果i和arr之间有适当的空间，利用数组的越界操作就可能覆盖到i，导致死循环的出现
//int main()
//{
//	int i = 0;
//	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	for (i = 0; i <= 12; i++)    // 越界访问
//	{
//		arr[i] = 0;
//		printf("Hello,world!\n");
//	}
//	return 0;
//}

//#include <assert.h>

//void my_strcpy(char* dest, const char* src) //防止src被修改	while (*src++ = *dest++)
//
//{
//	//断言
//	assert(src != NULL);
//	assert(dest != NULL);
//
//	while (*dest++ = *src++)
//	{
//		;
//	}
//}

//返回类型为char*，方便其返回值作另外一个函数的参数进行传递（方便链式访问）
//char* my_strcpy(char* dest, const char* src) // const防止src被修改	while (*src++ = *dest++)
//
//{
//	char* ret = dest;
//	//断言
//	assert(src != NULL);
//	assert(dest != NULL);
//
//	while (*dest++ = *src++)
//	{
//		;
//	}
//	return ret;
//}

//int main()
//{
//	char arr1[20] = "XXXXXXXXXXXX";
//	char arr2[] = "hello,bit";
//	// strcpy在拷贝字符串的时候，会把源字符串的\0也拷贝过去
//	//strcpy(arr1, arr2);
//	//char* p = NULL;
//	//my_strcpy(arr1, p);
//	//my_strcpy(arr1, arr2);
//	printf("%s", my_strcpy(arr1, arr2));
//	return 0;
//}


//int main()
//{
//	const int num = 10;
//	//num = 20;   //无法直接修改num
//
//	//int* p = &num;
//	//*p = 20;    //变向修改num
//
//
//	//const 修饰指针变量
//	//1.const 放在*的左边:
//	// 意思是p指向的对象不能通过p来改变,但p变量本身的值是可以改变的
//
//	//*p = 20;    //err
//	//const int* p = &num;   //int const* p  和 const int* p 一样意思
//
//	//int n = 100;
//	//*p = 100; //err
//	//p = &n; //ok
//
//
//	//2.const放在*的右边:
//	// 意思是p指向的对象是可以通过p来改变的，但是不能修改p变量本身的值
//
//	int* const p = &num;
//	*p = 0;//ok
//	int n = 100;
//	p = &n; //err
//
//
//	//3.*左右边均有const
//	// 意思是p指向的对象是不能通过p来改变的，也不能修改p变量本身的值
//	const int* const p = &num;
//
//
//	printf("%d\n", num);
//	return	0;
//}


//2024.4.10 调试（下）

//int my_strlen(const char* str)  //const能够防止*str的内容被修改
//{
//	int count = 0;
//	assert(str != NULL);  //若为假，则抛出异常警告；若为真，则程序继续走
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//	return count;
//}
//int main()
//{
//	char arr1[] = "abcdefg";
//	int len = my_strlen(arr1);
//	printf("%d\n", len);
//	return 0;
//}


//编译常见的错误：
//1. 编译型错误（语法错误）
//2. 链接型错误（链接期间）- 找不到符号
//3. 运行时错误（调试）



//2024.4.11
//三角形判断
//
//int main()
//{
//	int a = 0;
//	int b = 0;
//	int c = 0;
//	while (scanf("%d %d %d", &a, &b, &c) == 3)
//	{
//		//是三角形
//		if ((a + b > c) && (a + c > b) && (b + c > a))
//		{
//			if ((a == b && b != c) || (a == c && c != b) || (b == c && c != a))
//			{
//				printf("等腰三角形\n");
//			}
//			else if (a == b && b == c)
//			{
//				printf("等边三角形\n");
//			}
//			else
//			{
//				printf("普通三角形\n");
//			}
//		}
//		//不是三角形
//		else
//		{
//			printf("不是三角形\n");
//		}
//	}
//}

//写一个函数打印arr数组的内容，不使用数组下标，使用指针
//void print(int* arr, int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//}
//
//int main()
//{
//	int arr[5] = { 1, 2, 3, 4, 5 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	printf("%d", sz);
//	//print(arr, sz);
//	return 0;
//}

//将一个字符串str的内容颠倒过来，并输出
//int main()
//{
//	char arr[10000] = { 0 };
//	//scanf("%s", arr);   //scanf遇到空格就截断了，如输入abc defg, 输出为abc
//	gets(arr);            //换成gets()就没问题
//	//printf("%s", arr);
//	int left = 0;
//	int right = strlen(arr) - 1;  //求字符数组长度用strlen()，求整型数组长度用 sizeof(arr) / sizeof(arr[0])
//
//	while (left < right)
//	{
//		char tmp;
//		tmp = arr[left];
//		arr[left] = arr[right];
//		arr[right] = tmp;
//		left++;
//		right--;
//	}
//	printf("%s", arr);
//
//	return 0;
//}



//求Sn = a + aa + aaa + aaaa + aaaaa的前5项之和，其中a是一个数字，
//例如：2 + 22 + 222 + 2222 + 22222

//int main()
//{
//	int a = 0;
//	int n = 0;
//	scanf("%d %d", &a, &n); //前n项
//	int i = 0;
//	int k = 0;
//	int sum = 0;
//
//	for (i = 0; i < n; i++)
//	{
//		k = k * 10 + a;    // 2 、2 + 22
//		sum += k;
//	}
//	printf("%d\n", sum);
//	return 0;
//}

//打印水仙花数
//【题目内容】
// 
//求出0～100000之间的所有“水仙花数”并输出。
//“水仙花数”是指一个n位数，其各位数字的n次方之和确好等于该数本身，
//如 : 153＝1 ^ 3＋5 ^ 3＋3 ^ 3，则153是一个“水仙花数”

//int main()
//{
//	int i = 0;
//	for (i = 0; i <= 100000; i++)
//	{
//		//判断i是否为水仙花数
//		//1.计算i是几位数 -> n
//		int n = 1;   //任何一个数至少为一位数
//		int tmp = i;
//		int sum = 0;
//
//		while (tmp / 10)
//		{
//			n++;
//			tmp /= 10;
//		}
//		//2.得到i每一位，计算他的n次方之和
//		tmp = i;
//		while (tmp)
//		{
//			sum += pow(tmp % 10, n); // 
//			tmp /= 10;
//		}
//		if (sum == i)
//		{
//			printf("%d ", i);
//		}
//	}
//	return 0;
//}


//打印菱形

//int main()
//{
//	int line = 0;
//	scanf("%d", &line);
//
//	int i = 0;
//	//上
//	for (i = 0; i < line; i++)
//	{
//		//打印一行
//		//空格
//		int j = 0;
//		for (j = 0; j < line - 1 - i; j++)
//		{
//			printf(" ");
//		}
//		//*
//		for (j = 0; j < 2 * i + 1; j++)
//		{
//			printf("*");
//		}
//		printf("\n");
//	}
//	//下
//	for (i = 0; i < line - 1; i++)
//	{
//		//打印一行
//		//空格
//		int j = 0;
//		for (j = 0; j <= i; j++)
//		{
//			printf(" ");
//		}
//
//		//*
//		for (j = 0; j < 2 * (line - 1 - i) - 1; j++)
//		{
//			printf("*");
//		}
//		printf("\n");
//	}
//
//	return 0;
//}


//【题目名称】
//喝汽水问题
//【题目内容】
//喝汽水，1瓶汽水1元，2个空瓶可以换一瓶汽水，给20元，可以多少汽水（编程实现）。
//答案：39

//int main()
//{
//	int money = 0;
//	scanf("%d", &money);
//	int total = money;
//	int empty = money;
//
//	//置换
//	while (empty >= 2)
//	{
//		total += empty / 2;
//		empty = empty / 2 + empty % 2;  //用空瓶换来的汽水又喝完得到的空瓶 + 余下的空瓶
//
//	}
//
//	//if (money > 0)
//	//{
//	//	printf("%d\n", 2 * money - 1);
//	//}
//	//else
//	//{
//	//	printf("%d\n", 0);
//	//}
//
//	printf("%d\n", total);
//	return 0;
//}


// 2024.4.12
//初阶测评


//#include <stdio.h>
//
//int cnt = 0;
//int fib(int n)
//{
//	cnt++;
//	if (n == 0)
//	{
//		return 1;
//	}
//	else if (n == 1)
//	{
//		return 2;
//	}
//	else
//	{
//		return fib(n - 1) + fib(n - 2);
//	}
//}
//
//int main()
//{
//	fib(8);
//	printf("%d\n", cnt);  //即，fib()被调用的次数  67
//	return 0;
//}


//int main()
//{
//	int x = 1;
//	do
//	{
//		printf("%2d", x++);  //死循环
//
//	} while (x--);
//}

//int main()
//{
//	int i = 1;
//	int j;
//	j = i++;
//	printf("%d %d", i, j);  // 2  1
//	return 0;
//}


//int main()
//{
//	int i = 10;
//	int j = 20;
//	int k = 3;
//	k *= i + j;    //先 + 再 *= ，*=这类操作符优先级 比 + 这类操作符优先级更低
//	printf("%d", k);  //90
//
//	return 0;
//}



//int a = 1;
//void test()
//{
//	int a = 2;
//	a += 1;    //局部和全局变量都同名时，这里a += 1是局部的a
//}
//
//int main()
//{
//	test();
//	printf("%d\n", a);  // 打印全局变量a = 1
//	return 0;
//}

//编译程序的时候，注释是被删除掉的

//int main()
//{
//	int a = 0, c = 0;
//	do
//	{
//		--c;          // -1
//		a = a - 1;    // -1
//	} while (a > 0);
//
//	printf("%d\n", c);  // -1
//	return 0;
//}

//int main()
//{
//	double x = 2;
//	double y = x + 3 / 2;  // 2 + 1
//	printf("%lf\n", y);  // 3.000000
//	return	0;
//}


//求循环次数
//for (x = 0. y = 0; (y = 123) && (x < 4); x++)
//{
//	//循环4次
//}


//int main()
//{
//	int year = 1009, * p = &year;
//	//等价写法
//	//int year = 1009;
//	//int* p = &year;
//
//	//后置++优先级比*高，但是它是后置的，所以先执行*p,然后执行 p = p + 1(地址+1)
//	*p++;
//}

//求最小公倍数
//方法1
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	int m = (a > b ? a : b);
//	while (1)
//	{
//		if (m % a == 0 && m % b == 0)
//		{
//			break;
//		}
//		m++;
//	}
//	printf("%d", m);
//	return 0;
//}

//方法2  效率高
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	//计算a和b的最小公倍数
//	int i = 1;
//	while (a * i % b)
//	{
//		i++;
//	}
//	//打印
//	printf("%d\n", i * a);
//	return 0;
//}

//字符串倒置
//输入I like Beijing.
//输出Beijing. like I


//void reverse(char* left, char* right)
//{
//	while (left < right)
//	{
//		char tmp = *left;
//		*left = *right;
//		*right = tmp;
//		left++;
//		right--;
//	}
//}


//int main()
//{
//	char arr[100] = { 0 };
//	//输入
//	gets(arr);
//	//逆置
//	int len = strlen(arr);
//	//1.逆置整个字符串(巧妙)
//	reverse(arr, arr + len - 1);
//
//	//2.逆置每个单词:找到空格位置，然后逆置该单词
//	char* start = arr;
//	while (*start != '\0')
//	{
//		char* end = start;
//		while (*end != ' ' && *end != '\0')
//		{
//			end++;
//		}
//		reverse(start, end - 1);
//		if (*end != '\0')
//			end++;
//		start = end;
//	}
//	printf("%s\n", arr);
//	return 0;
//}

//2024,4.13

//int main()
//{
//	int i = 0;
//	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	for (i = 0; i <= 12; i++)
//	{
//		arr[i] = 0;
//		printf("hello,world!\n");   //debug x86是死循环，debug x64不会死循环，内存开辟方式
//	}
//	return 0;
//}

//unsigned  无符号数，最高位也是有效位，算进数值中的
//signed  有符号数，最高位是符号位，0为正数，1为负数


//第一个void表示函数不会返回值
//第二个void表示函数不需要传参

//void test(void)
//{
//	printf("Hello,world!\n");
//}
//
//int main()
//{
//	test(1);
//	return 0;
//}


//判断当前机器的字节序

//int main()
//{
//	int a = 1;
//	//整型变量a取地址解引用是访问4个字节，现强制类型转换char*，则解引用是访问1个字节的内容
//	if (*((char*)&a) == 1)
//	{
//		printf("小端\n");
//
//	}
//	else
//	{
//		printf("大端\n");
//	}
//}


//负数：补码=原码取反 + 1
//负数：原码=补码取反 + 1
//补码和原码的相互转换的操作统一起来了

//signed short取值范围：-32768~32767
//unsigned short取值范围：0~65535

// 10000000 00000000 00000000 00000001  -> 整型的 -1 原码
// 11111111 11111111 11111111 11111110  -> 整型的 -1 反码
// 11111111 11111111 11111111 11111111  -> 整型的 -1 补码
// 11111111  -> 赋值到char型变量要截断
// %d打印的是有符号整型
// 11111111 需要整型提升 -> unsigned char为无符号位，高位补0 -> 00000000 00000000 00000000 11111111 （补码）正数 255
// 整型提升-> signed 高位补位看符号位是什么就补什么；无符号数高位直接补0


//int main()
//{
//	char a = -1;            //其实就是signed char
//	signed char b = -1;     //signed char 取值范围： -128~127
//	unsigned char c = -1;   //unsigned char 取值范围：0~255
//
//	printf("a = %d, b = %d, c = %d", a, b, c); // -1 -1 255
//	return 0;
//}



//int main()
//{
//	//char -128~127
//	char a = -128;  
//
//	//10000000 00000000 00000000 10000000  -128原码
//	//11111111 11111111 11111111 01111111  反码
//	//11111111 11111111 11111111 10000000  补码
//	//10000000 截断 -> a, 高位为1
//	//整型提升，char为有符号char，高位为1，所以高位补1 -> 11111111 11111111 11111111 10000000
//	//无符号数打印：11111111 11111111 11111111 10000000 （4294967168）
//
//	printf("%u\n", a); //打印无符号整数 4294967168
//	return 0;
//}


//int main()
//{
//	char a = 128;
//	printf("%u\n", a);  //4294967168
//	printf("%d\n", a);  //-128
//	return 0;
//}

//int main()
//{
//	int i = -20;
//	unsigned int j = 10;
//	printf("%d\n", i + j);  // -10,若怕错就转换成二进制进行运算
//	return 0;
//}

// 2024.4.14
//int main()
//{
//	unsigned int i;    // unsigned int 是  >= 0
//	for (i = 9; i >= 0; i--)
//	{
//		//当i = -1时，其内存的补码为11111111 11111111 11111111 11111111，打印其无符号数，则是一个很大的正数
//		printf("%u\n", i);   // 9 8 7 6 5 4 3 2 1 0 4294967295 4294967294 ....死循环
//
//	}
//	return 0;
//}


//int main()
//{
//	char a[1000];  //vs、大部分编译器char是signed char
//	int i;
//	for (i = 0; i < 1000; i++)
//	{
//		a[i] = -1 - i;
//
//	}
//	//arr[i] --> char 范围-128~127
//	//-1 -2 -3 -4 ... -1000 error
//	// -1 -2 ... -128 127 126 125 ... 3 2 1 0 -1...
//	// 128 + 127 = 255
//	//strlen()是求字符串的长度，关注的是字符串中'\0'（ascii为0）之前出现多少字符
//
//	printf("%d\n", strlen(a));  // 255
//	return 0;
//}


//unsigned char i = 0;  //取值范围是0~255
//int main()
//{
//	for (i = 0; i <= 255; i++)
//	{
//		printf("hello,world\n"); // 死循环
//
//	}
//	return 0;
//}

//int main()
//{
//	// strlen()返回值类型为size_t，为unsigned int 无符号数
//	// 无符号数 - 无符号数 = 无符号数
//	if (strlen("abc") - strlen("abcdef") >= 0)  //3 - 6 = -3，-3被当成无符号数则是一个很大的数
//	{
//		printf(">\n");   // 输出 >
//	}
//	else
//	{
//		printf("<\n");
//	}
//	return 0;
//}


// 浮点型在内存中的存储


//int main()
//{
//	//以整数(浮点数...)的方式存储的，就要以整数(浮点数...)的方式进行访问
//	//不然访问出来的数值就不是所希望得到的
//	int n = 9;
//
//	//00000000 00000000 00000000 00001001
//	//0 00000000  00000000000000000001001
//	//E=1-127=-126
//	//M=0.00000000000000000001001
//	//+ 0.00000000000000000001001 * 2^-126  接近于0
//
//
//	float* pFloat = (float*)&n;
//	printf("n的值为：%d\n", n);   // 9  整数的方式存储，整数的方式进行访问,没问题
//	printf("*pFloat的值为：%f\n", *pFloat);// 0.000000  整数的方式存储，浮点的方式进行访问,有问题
//	*pFloat = 9.0;
//	// 1001.0
//	// 1.001 * 2^3
//	// s=0, e=3, m=001
//	// 0 10000010(127+3=130) 00100000000000000000000
//	// 01000001000100000000000000000000保存在内存中，以%d打印则是1091567616
//	printf("num的值为：%d\n", n);   // 1091567616
//	printf("*pFloat的值为：%f\n", *pFloat);  //9.000000
//	return 0;
//}


//int main()
//{
//	float f = 5.5;
//	//5.5
//	//101.1
//	//1.011 * 2^2
//	//s=0; m=1.011;e=2
//	// 0（正数s为0，负数为1） 10000001（e=2 + 127中间值 = 129） 01100000000000000000000（m的小数点前的1省略，保存011，并用0补到23位）
//	// 0100 0000 1011 0000 0000 0000 0000 0000
//	// 4      0   B    0    0    0     0    0
//	// 0x40b00000
//	// 2+127=129
//	return 0;
//}

//【题目名称】
//调整奇数偶数顺序

//【题目内容】
//调整数组使奇数全部都位于偶数前面。


//void move_arr(int* arr, int sz)
//{
//	int left = 0;
//	int right = sz - 1;
//	while (left < right)
//	{
//		//从左到右找一个偶数，停下来
//		while ((left < right) && (arr[left] % 2 == 1))
//		{
//			left++;
//		}
//		//从右向左找一个奇数，停下来
//		while ((left < right) && (arr[right] % 2 == 0))
//		{
//			right--;
//		}
//		//交换奇数和偶数
//		if (left < right)
//		{
//			int tmp = arr[left];
//			arr[left] = arr[right];
//			arr[right] = tmp;
//			left++;
//			right--;
//		}
//	}
//}


//int main()
//{
//	int arr[10] = { 0 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		scanf("%d", arr + i);
//	}
//	//调整
//	move_arr(arr, sz);
//	//输出 
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//
//}

//输入描述:
//输入包含三行，
//第一行包含两个正整数n，m，用空格分隔。n表示第二行第一个升序序列中数字的个数，m表示第三行第二个升序序列中数字的个数。
//第二行包含n个整数，用空格分隔。
//第三行包含m个整数，用空格分隔
//输出描述 :
//输出为一行，输出长度为n + m的升序序列，即长度为n的升序序列和长度为m的升序序列中的元素重新进行升序序列排列合并。

//int main()
//{
//	int n = 0;
//	int m = 0;
//	scanf("%d %d", &n, &m);
//	int arr1[n];
//	int arr2[m];
//	int arr3[m + n];   //存放合并后的数组
//
//	int i = 0;
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", arr1 + i);
//
//	}
//
//	for (i = 0; i < m; i++)
//	{
//		scanf("%d", arr2 + i);
//
//	}
//	//合并打印
//	int j = 0;
//	int k = 0;
//	int r = 0;
//	while (j < n && k < m)
//	{
//		if (arr1[j] < arr2[k])
//		{
//			//arr3[r++] = arr1[j];
//			printf("%d ", arr1[j]);
//			j++;
//		}
//		else
//		{
//			//arr3[r++] = arr2[k];
//			printf("%d ", arr2[k]);
//			k++;
//		}
//	}
//	if (j < n)
//	{
//		for (; j < n; j++)
//		{
//			//arr3[r++] = arr1[j];
//			printf("%d ", arr1[j]);
//
//		}
//	}
//	else
//	{
//		for (; k < m; k++)
//		{
//			//arr3[r++] = arr2[k];
//			printf("%d ", arr2[k]);
//
//		}
//	}
//
//	//for (i = 0; i < m + n; i++)
//	//{
//	//	printf("%d ", arr3[i]);
//	//}
//	return 0;
//}


//指针进阶

//int main()
//{
//	//字符串指针
//	//char ch = 'a';
//	//char* pch = &ch;
//	//*pch = 'b';
//	//printf("%c\n", ch);
//
//	char* p = "abcdefg";	//把字符串首字符a的地址赋值给p
//	//*p = 'w';           	//abcdefg为常量字符串,是不能修改的
//
//	printf("%s\n", p);
//
//	return 0;
//
//}


//int main()
//{
//	const char* p1 = "abcdef";
//	const char* p2 = "abcdef";
//
//	char arr1[] = "abcdef";
//	char arr2[] = "abcdef";
//
//	if (p1 == p2)
//	{
//		printf("p1 == p2\n");   //打印
//
//	}
//	else
//	{
//		printf("p1 != p2\n");
//	}
//
//	if (arr1 == arr2)
//	{
//		printf("arr1 == arr2\n");
//
//	}
//	else
//	{
//		printf("arr1 != arr2\n"); //打印
//	}
//	return 0;
//}
//指针数组 -> 是数组 -> 用来存放指针的数组

//int main()
//{
//	int arr1[] = { 1, 2, 3, 4, 5 };
//	int arr2[] = { 3, 4, 5, 6, 7 };
//	int arr3[] = { 8, 9, 0, 1, 2 };
//
//	int* parr[3] = { arr1, arr2, arr3 };  //存放整型指针的数组
//
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 5; j++)
//		{
//			//printf("%d ", *(parr[i] + j));
//			printf("%d ", parr[i][j]);   // *(p+i) == p[i]
//
//		}
//		printf("\n");
//	}
//	return 0;
//}


//数组指针 -> 指向数组的指针
// int (*p)[10],数组指针


//再次讨论数组名
//int main()
//{
//	int arr[10] = { 0 };
//	int* p = arr;
//	int(*p)[10] = &arr;    //(数组的地址)数组指针的赋值,如果这里的数组指针解引用后为arr数组名，
						   // 该数组名也还是个地址（指向数组首元素的地址）
//
//
//	printf("%p\n", arr);
//	printf("%p\n", arr + 1);
//
//
//	printf("%p\n", &arr[0]);
//	printf("%p\n", &arr[0] + 1);
//
//
//	printf("%p\n", &arr);
//	printf("%p\n", &arr + 1);
//
//
//	int sz = sizeof(arr);
//	printf("%d\n", sz);
//
//	return 0;
//}
// 数组名通常表示都是数组首元素地址
//但有2个例外：
//1.sizeof(数组名)，这里的数组名表示数组，计算的是整个数组的大小
//2.&数组名，这里的数组名表示的依然是整个数组，所以&数组名取出的是整个数组地址


//2024.4.15
//数组指针
//int main()
//{
//	char* arr[5] = { 0 };
//	char* (*parr)[5] = &arr;  //数组指针
//
//
//	//二级指针 -> 存放一级指针变量的地址
//	char ch = 'w';
//	char* p1 = &ch;
//	char** p2 = &p1;
//}


//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* p = arr;
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(p + i));
//
//	}
//
//	//比较别扭的写法，常见的数组指针用法是用在二维数组上
//	//int(*p)[10] = &arr;   //这里的p的类型是int (*)[10]
//	//int i = 0;
//	//int sz = sizeof(arr) / sizeof(arr[0]);
//	//for (i = 0; i < sz; i++)
//	//{
//	//	// p是指向数组的，*p其实就是相当于数组名，数组名又是数组首元素的地址
//	//	// 所以*p本质是数组首元素的地址
//	//	printf("%d ", *(*p + i));
//	//}
//	return 0;
//}


//void print1(int arr[3][5], int r, int c)
//{
//	int i = 0;
//	for (i = 0; i < r; i++)
//	{
//		int j = 0;
//		for (j = 0; j < c; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//}

//int(*p)[5]中的数组指针p是指向二维数组的第一行，该行有5个int型的数值，p+1则指向第二行，,...
//void print2(int(*p)[5], int r, int c)
//{
//	int i = 0;
//	for (i = 0; i < r; i++)
//	{
//		int j = 0;
//		for (j = 0; j < c; j++)
//		{
//			//p+i即为第i行的地址， *（p+i）拿到第i行的数组名，即arr[i],第i行首元素的地址
//			//*（p+i）是第i行的首地址, 所以*（p+i） + j是这一行下标为j的地址
//			// *(*(p + i) + j)这就拿到了第i行，下标为j的元素的值
//			printf("%d ", *(*(p + i) + j));
//			//也可以写成
//			printf("%d ", p[i][j]);
//		}
//		printf("\n");
//	}
//}


//int main()
//{
//	//二维数组的数组名arr表示首元素的地址，这个首元素是它的第一行
//	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
//	//二维数组arr[3][5],arr表示二维数组首元素地址，即表示第一行的地址（是一个一维数组的地址）
//	//那么，数组的地址应存放到数组指针中
//	print2(arr, 3, 5);
//	return 0;
//}

//int main()
//{
//	int arr[5];       // arr是整型数组
//	int* parr1[10];   // parr1是整型指针数组
//	int(*parr2)[10];  // parr2是数组指针
//
//	// parr3是存放数组指针的数组，parr3包含10个元素，每个元素均为数组指针，每个数组指针指向一个有5个int型的数组
//	int(*parr3[10])[5];
//}

//数组参数和指针参数
//void test(int arr[])//ok
//{}
//
//void test(int arr[10])//ok
//{}
//
//void test(int* arr) //ok
//{}
//
//void test2(int* arr[20]) //ok
//{}
//
//void test2(int** arr) //ok
//{}
//
////一维数组传参
//int main()
//{
//	int arr[10] = { 0 };
//	int* arr2[20] = { 0 };   //指针数组
//	test(arr);
//	test2(arr2);
//}

//二维数组传参
//void test(int arr[3][5]) //ok
//{}
//
//void test(int arr[][])//error  ,原因：行能省略，但列不能省略
//{}
//
//void test(int arr[][5])//ok
//{}



//void test(int* arr) //error 一维数组的地址需要数组指针变量来存放，int* arr一级指针
//{}
//
//void test(int* arr[5]) // error int* arr[5]为指针数组，不是指针
//{}
//
//void test(int(*arr)[5]) //ok
//{}
//
//void test(int** arr) //error  一维数组的地址用数组指针变量来存放，不是用二级指针来存放
//{}
//
//int main()
//{
//	int arr[3][5] = { 0 };
//	//二维数组的数组名，表示首元素的地址，其实是第一行的地址
//	//第一行是一个一维数组
//	test(arr);
//}

// 一级指针传参
//void print(int* p, int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d\n", *(p + i));
//	}
//}

//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = arr;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	//一级指针p，传给函数
//	print(p, sz);   //ok
//	return 0;
//}

//二级指针传参
//void test(int** ptr)
//{
//	printf("num = %d\n", **ptr);
//
//}

//int main()
//{
//	int n = 10;
//	int* p = &n;
//	int** pp = &p;
//	test(pp);  //ok
//	test(&p);  //ok
//	return	0;
//}

//函数指针 -> 指向函数的指针
//int Add(int x, int y)
//{
//	return x + y;
//
//}
//
//int main()
//{
//	int arr[5] = { 0 };
//	//&数组名 - 取出的数组的地址
//	int(*p)[5] = &arr;           //这个不是二级指针
//
//	//&函数名 - 取出的是函数的地址
//	//对函数来说，&函数名和函数名都是函数的地址，一样的
//	printf("%p\n", &Add);
//	printf("%p\n", Add);
//
//
//	//函数指针,以下写法一样的
//	int (*pf)(int, int) = &Add;
//	int (*pf)(int, int) = Add;
//
//
//	//对函数指针解引用，以下写法一样的
//	int ret = (*pf)(2, 3);   //Add(2, 3)
//	int ret = pf(2, 3);      //解引用*可写可不写
//	printf("%d\n", ret);
//	return 0;
//}


//int main()
//{
//	//指针数组
//	int* arr[4];
//	char* ch[5];
//	int** p = arr;
//
//	//数组指针
//	int arr2[5];
//	int(*pa)[5] = &arr2;
//
//	char* arr3[6];
//	char* (*p3)[6] = &arr3;
//	return 0;
//}


//int test(const char* str)
//{
//	printf("%s\n", str);
//	return 0;
//}
//int main()
//{
//	//函数指针-> 指向函数的指针
//	//printf("%p\n", &test);
//	//printf("%p\n", test);
//
//	//pf指向的函数参数为 const char* 类型，返回值为int型
//	int (*pf)(const char*) = test;
//
//	//通过函数指针调用test（）
//	//一样的
//	pf("abc");
//	(*pf)("abc"); // *可看成解引用，其实不写也行
//
//	//printf("%zu", sizeof(pf));    //4或者8字节
//	return 0;
//}


//int main()
//{
//	//1. void(*)() :             为函数指针类型
//	//2. (  void(*)()  )    0:   0原本是int型，现将0强制类型转换成 void(*)()函数指针类型，0变成了该函数的地址
//	//3.  *(  void(*)()  )    0: 对该地址进行解引用来找到这个函数（其实这颗*可有可无的）
//	//4. (     *(  void(*)()  )    0     )():  然后传入空参数
//	//总结：这句代码是一次函数调用，调用的是0作为地址处的函数
//	(*(void(*)())    0)();
//
//
//
//	//signal是函数名，以上代码是一次函数声明
//	// 声明的signal函数的第一个参数类型是int，第二个参数的类型是函数指针，该函数指针指向的函数参数是int，返回类型是void
//	// signal函数的返回类型也是一个函数指针，该函数指针指向的函数参数是int，返回类型是void
//	void (*signal(int, void(*)(int)))(int);
//
//	return 0;
//}




//简化	void (   *signal(    int,     void(*)(int)      )     )(int);

//typedef unsigned int  uint;
////typedef void(*)(int) pf_t;  //这是错位的类型重命名
//typedef void(*pf_t)(int);     //把void(*)(int)类型重命名为pf_t

//int main()
//{
//	void (*signal(int, void(*)(int)))(int);
//	//改下成
//	pf_t signal(int, pf_t);
//
//}


//函数指针用途
//写一个计算器：加减乘除

//void menu()
//{
//	printf("*********************************\n");
//	printf("*******  1.add  2.sub    ********\n");
//	printf("*******  3.mul  4.div    ********\n");
//	printf("*******      0.exit      ********\n");
//	printf("*********************************\n");
//}
//
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//int Mul(int x, int y)
//{
//	return x * y;
//}
//int Div(int x, int y)
//{
//	return x / y;
//
//}
//
////使用函数指针:算是比较高大上的东西
//void calc(int(*pf)(int, int))
//{
//	int x = 0;
//	int y = 0;
//	int ret = 0;
//
//	printf("请输入2个操作数:>");  //发现代码冗余，可以使用函数指针解决
//	scanf("%d %d", &x, &y);
//	ret = pf(x, y);
//	printf("%d\n", ret);
//
//}
//
//int main()
//{
//	int input = 0;
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//
//		switch (input)
//		{
//		case 1:
//			//printf("请输入2个操作数:>");  //发现代码冗余，可以使用函数指针解决
//			//scanf("%d %d", &x, &y);
//			//ret = Add(x, y);
//			//printf("%d\n", ret);
//			calc(Add);
//			break;
//
//		case 2:
//			//printf("请输入2个操作数:>");
//			//scanf("%d %d", &x, &y);
//			//ret = Sub(x, y);
//			//printf("%d\n", ret);
//			calc(Sub);
//			break;
//
//		case 3:
//			//printf("请输入2个操作数:>");
//			//scanf("%d %d", &x, &y);
//			//ret = Mul(x, y);
//			//printf("%d\n", ret);
//			calc(Mul);
//			break;
//
//		case 4:
//			//printf("请输入2个操作数:>");
//			//scanf("%d %d", &x, &y);
//			//ret = Div(x, y);
//			//printf("%d\n", ret);
//			calc(Div);
//			break;
//
//		case 0:
//			printf("退出计算器");
//			break;
//
//		default:
//			printf("选择错误");
//			break;
//		}
//	} while (input);
//	return 0;
//}


//2024.4.16
//函数指针数组 -> 存放函数指针的数组

//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//int Mul(int x, int y)
//{
//	return x * y;
//}
//int Div(int x, int y)
//{
//	return x / y;
//
//}
//
//int main()
//{
//	//函数指针
//	int (*pf)(int, int) = Add;
//	//函数指针数组，其类型是int (*)(int, int)函数指针类型
//	int (*arr[4])(int, int) = { Add, Sub, Mul, Div };
//
//	//调用函数指针数组里面的函数
//	int i = 0;
//	for (i = 0; i < 4; i++)
//	{
//		int ret = arr[i](5, 5);
//		printf("ret = %d\n", ret);
//	}
//	return 0;
//}


//void menu()
//{
//	printf("*********************************\n");
//	printf("*******  1.add  2.sub    ********\n");
//	printf("*******  3.mul  4.div    ********\n");
//	printf("*******      0.exit      ********\n");
//	printf("*********************************\n");
//}
//
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//int Mul(int x, int y)
//{
//	return x * y;
//}
//int Div(int x, int y)
//{
//	return x / y;
//
//}
//
//
//int main()
//{
//	int input = 0;
//	int x = 0;
//	int y = 0;
//	int ret = 0;
//
//	函数指针数组,使得程序更加便捷
//	int (*pfArr[])(int, int) = { 0, Add, Sub,Mul, Div };
//
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//		if (input == 0)
//		{
//			printf("退出计算器\n");
//		}
//		else if (input >= 1 && input <= 4)
//		{
//			printf("请输入2个操作数:>");
//			scanf("%d %d", &x, &y);
//
//			ret = pfArr[input](x, y);		//函数指针数组来调用函数
//
//			printf("%d\n", ret);
//		}
//		else
//		{
//			printf("选择错误，请重新选择\n");
//		}
//	} while (input);
//	return 0;
//}


//指向函数指针数组的指针

//int main()
//{
//	//函数指针数组
//	int (*pfArr[5])(int, int) = { 0, Add, Mul, Sub, Div };
//
//	//指向【函数指针数组】的指针
//	int (*(*ppfArr)[5])(int, int) = &pfArr;
//}

//回调函数：通过函数指针调用的函数
//冒泡排序

//void bubble_sort(int arr[], int sz)
//{
//	int i = 0;
//	//趟数
//	for (i = 0; i < sz - 1; i++)
//	{
//		int flag = 1; // 假设数组是排好序的
//		//一趟冒泡排序的过程
//		int j = 0;
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			if (arr[j] > arr[j + 1])
//			{
//				int tmp = arr[j];
//				arr[j] = arr[j + 1];
//				arr[j + 1] = tmp;
//				flag = 0;
//			}
//		}
//		if (flag == 1)
//		{
//			break;
//		}
//	}
//}

//库函数：qsort-这个函数可以排序任意类型的数据
//void qsort(void* base,   //要排序数据的起始位置
//	         size_t num,   //待排序的数据元素个数
//	         size_t width, //(一个)待排序的数据元素的大小 单位是字节
//	         int (*cmp)(const void* e1, const void* e2) //函数指针-比较函数（可以排序任意类型的数据）
//);

//比较2个整型元素
//e1指向一个整数
//e2指向另外一个整数
//int cmp_int(const void* e1, const void* e2)
//{
//	//if (*(int*)e1 > *(int*)e2)   // 注意：void* e1是不能直接解引用操作的
//	//	return 1;
//	//else if (*(int*)e1 == *(int*)e2)
//	//	return 0;
//	//else
//	//	return -1;
//
//	return (*(int*)e1 - *(int*)e2);//默认升序
//	//return (*(int*)e2 - *(int*)e1);//降序
//
//}

//void test1()
//{
//	int arr[] = { 9, 8,7,6,5,4,3,2,1,0 };
//	//把数组排成升序
//
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	//bubble_sort(arr, sz);
//
//	qsort(arr, sz, sizeof(arr[0]), cmp_int);
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//}

//struct Stu
//{
//	char name[20];
//	int age;
//};
//
//int cmp_stu_by_name(const void* e1, const void* e2)
//{
//	//strcmp --> >0 ==0 <0
//	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
//}
//
//int cmp_stu_by_age(const void* e1, const void* e2)
//{
//
//	return (((struct Stu*)e1)->age - ((struct Stu*)e2)->age);
//}


//void test2()
//{
//	//测试使用qsort来排序结构体数据
//	struct Stu s[] = { {"zhangsan", 15}, { "lisi", 30 }, { "wangwu", 25 } };
//	int sz = sizeof(s) / sizeof(s[0]);
//	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);  //按照名字排序
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);     //按照年龄排序
//
//}


//int main()
//{
//	int a = 10;
//	char* pa = &a;  //char*  =  int* 会报警告
//
//	//void*是无具体类型的指针，所以不能解引用操作，也不能+-整数运算
//	//void* 是无具体类型的指针，可以接受任意类型的地址
//	void* pv = &a;    //ok
//
//	return 0;
//
//}


//把冒泡排序函数改造成qsort()型的函数
//void Swap(char* buf1, char* buf2, int width)  // width为一个元素所占的字节数
//{
//	int i = 0;
//	for (i = 0; i < width; i++)
//	{
//		char tmp = *buf1;
//		*buf1 = *buf2;
//		*buf2 = tmp;
//		buf1++;
//		buf2++;
//	}
//}
//
//void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
//{
//	int i = 0;
//	//趟数
//	for (i = 0; i < sz - 1; i++)
//	{
//		int flag = 1; // 假设数组是排好序的
//		//一趟冒泡排序的过程
//		int j = 0;
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
//			{
//				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
//				flag = 0;
//			}
//		}
//		if (flag == 1)
//		{
//			break;
//		}
//	}
//}
//
//
//void test3()
//{
//	int arr[] = { 9, 8,7,6,5,4,3,2,1,0 };
//	//int arr2[] = { 0, 1, 2, 3, 4,5,6, 7,8,9 };
//
//	//把数组排成升序
//
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	//bubble_sort(arr, sz);
//	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
//	//qsort(arr, sz, sizeof(arr[0]), cmp_int);
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//}
//
//void test2()
//{
//	//测试使用qsort来排序结构体数据
//	struct Stu s[] = { {"zhangsan", 15}, { "lisi", 30 }, { "wangwu", 25 } };
//	int sz = sizeof(s) / sizeof(s[0]);
//	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);  //按照名字排序
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);     //按照年龄排序
//
//}
//void test4()
//{
//	//测试使用qsort来排序结构体数据
//	struct Stu s[] = { {"zhangsan", 15}, { "lisi", 30 }, { "wangwu", 25 } };
//	int sz = sizeof(s) / sizeof(s[0]);
//	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);  //按照名字排序
//	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);     //按照年龄排序
//
//}
//
//int main()
//{
//	//test1();   //测试整型数组的排序
//	//test2();     //测试使用qsort来排序结构体数据
//	//test3();     //测试qsort型的bubble_sort来排序整型数组
//	test4();     //测试qsort型的bubble_sort来排序结构体数组
//	return 0;
//}


//2024.4.17
//笔试题详解(1)

//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int Mul(int x, int y)
//{
//	return x * y;
//}
//
//
//int main()
//{
//	//整型指针
//	int a = 0;
//	int* pa = &a; 
//
//	//字符指针
//	char b = 'w';
//	char* pb = &b; 
//	
//
//	//数组指针
//	int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//	int (*pa)[10] = &arr;
//
//	//指针数组
//	int* ppa;
//	int* ppb;
//	int* ppc;
//	int* pb[10] = { ppa, ppb, ppc };
//
//	//函数指针
//	int (*pf)(int, int) = &Add;
//	//int (*pf)(int, int) = Add;
//
//	int sum = (*pf)(2, 3);   //函数指针的使用
//	//int sum = pf(2, 3);   //函数指针的使用
//
//	//函数指针数组
//	int (*ppf[3])(int, int) = { Add, Sub, Mul }; //ppf数组的每个元素类型是 int (*)(int, int)函数指针类型
//
//	//回调函数：通过函数指针调用的函数就是回调函数
//}


//数组名的理解
//指针的运算和指针类型（重点关注指针类型，它决定了解引用访问的权限）
//int main()
//{
//	//一维数组
//	int a[] = { 1,2,3,4 };
//
//	//sizeof(数组名)，数组名表示整个数组，计算的是整个数组的大小，单位字节
//	printf("%d\n", sizeof(a));        //16
//
//	//a + 0此时的a不是单独放在sizeof内部，也没有取地址，所以a就是首元素的地址
//	//是地址，大小就是4/8字节
//	printf("%d\n", sizeof(a + 0));    //4  a <===> &a[0]  a+0 <===> &a[0] + 0
//
//	//*a中的a是数组首元素的地址，*a就是对首元素的地址解引用，找到的就是首元素
//	printf("%d\n", sizeof(*a));       //4  *a <===> *&a[0] <===> a[0]
//
//	//这里的a是数组首元素的地址
//	//a+1是第二个元素的地址
//	printf("%d\n", sizeof(a + 1));    //4
//
//	//计算的是第二个元素的大小
//	printf("%d\n", sizeof(a[1]));     //4
//
//	//&a取出的数组的地址，是地址其大小是4/8字节
//	printf("%d\n", sizeof(&a));       //4
//
//	//*和&抵消，sizeof(a)=整个数组的大小
//	printf("%d\n", sizeof(*&a));      //16
//
//	//&a取出的是数组的地址，&a --> int(*)[4], &a + 1跳过整个(4个整型元素的)a的数组
//	//是地址，大小即4或8
//	printf("%d\n", sizeof(&a + 1));   //4
//
//	//&a[0]就是第一个元素的地址，其大小是4或8
//	printf("%d\n", sizeof(&a[0]));    //4
//
//	//&a[0] + 1是第二个元素的地址，等价于&a[1],其大小为4或8字节
//	printf("%d\n", sizeof(&a[0] + 1));//4
//}



//int main()
//{
//	//字符数组
//	char arr[] = { 'a','b','c','d','e','f' };
//
//	//sizeof(数组名)整个数组的大小
//	printf("%d\n", sizeof(arr));          //6
//
//	//arr + 0是数组首元素的地址
//	printf("%d\n", sizeof(arr + 0));      //4
//
//	//*arr就是数组的首元素
//	//*arr --> arr[0]
//	//*(arr + 0) --> arr[0]
//	printf("%d\n", sizeof(*arr));         //1    
//	printf("%d\n", sizeof(arr[1]));       //1
//
//	//&arr是数组地址
//	printf("%d\n", sizeof(&arr));         //4
//
//	//&arr + 1是数组指针，它跳过整个数组，它还是个地址
//	printf("%d\n", sizeof(&arr + 1));     //4
//	//&arr[0] + 1是第二个元素的地址
//	printf("%d\n", sizeof(&arr[0] + 1));  //4
//}



//int main()
//{
//	//函数原型：size_t strlen(const char* string);
//
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%d\n", strlen(arr));           //随机值（遇到0、\0才会停止）
//	printf("%d\n", strlen(arr + 0));       //随机值
//
//
//	//printf("%d\n", strlen(*arr));          // --> strlen('a') --> strlen(97) //野指针
//	//printf("%d\n", strlen(arr[1]));        // --> strlen('b') --> strlen(98) //野指针
//
//	printf("%d\n", strlen(&arr));          //虽然是数组指针，但使用strlen()还是会将其转换成const char *类型，随机值
//	printf("%d\n", strlen(&arr + 1));      //随机值-6
//	printf("%d\n", strlen(&arr[0] + 1));   //随机值-1
//
//}


//int main()
//{
//	char arr[] = "abcdef";                //[a b c d e f \0]
//	//printf("%d\n", sizeof(arr));          // 7
//
//	////arr为首元素地址，arr+0还是首元素地址，大小4或8
//	//printf("%d\n", sizeof(arr + 0));      // 4
//
//	////*arr  --> arr[0]
//	////*(arr + 0) --> arr[0]
//	//printf("%d\n", sizeof(*arr));         // 1
//
//	//printf("%d\n", sizeof(arr[1]));       // 1
//
//	////&arr取整个数组的地址
//	//printf("%d\n", sizeof(&arr));         // 4
//	//printf("%d\n", sizeof(&arr + 1));     // 4
//	//printf("%d\n", sizeof(&arr[0] + 1));  // 4
//
//	//strlen()是求字符串长度的，关注的是字符串中的\0，计算的是\0之前出现的字符的个数
//	//strlen是库函数，只针对字符串
//
//	//sizeof()只关注占用内存空间的大小，不在乎内存中放的是什么
//	//sizeof是操作符
//	
//	char arr[] = "abcdef";                //[a b c d e f \0]
//	printf("%d\n", strlen(arr));         // 6
//	printf("%d\n", strlen(arr + 0));     // 6
//	printf("%d\n", strlen(*arr));        //野指针
//	printf("%d\n", strlen(arr[1]));      //野指针
//	printf("%d\n", strlen(&arr));        //6
//	printf("%d\n", strlen(&arr + 1));    //随机值
//	printf("%d\n", strlen(&arr[0] + 1)); //5 
//
//}


//int main()
//{
//	char* p = "abcdef";
	//	printf("%d\n", sizeof(p));          // 4  指针
	//	printf("%d\n", sizeof(p + 1));      // 4  指针
	//	printf("%d\n", sizeof(*p));         // 1  字符‘a’
	//	printf("%d\n", sizeof(p[0]));       // 1  p[0] --> *(p + 0) --> *p
	//	printf("%d\n", sizeof(&p));         // 4  二级指针
	//	printf("%d\n", sizeof(&p + 1));     // 4  二级指针 + 1
	//	printf("%d\n", sizeof(&p[0] + 1));  // 4  字符‘b’的地址
	//
	//	printf("%d\n", strlen(p));          // 6
	//	printf("%d\n", strlen(p + 1));      // 5
	//	printf("%d\n", strlen(*p));         // ‘a’,野指针
	//	printf("%d\n", strlen(p[0]));       //p[0] --> *(p + 0) --> *p 野指针
	//	printf("%d\n", strlen(&p));         // 随机值
	//	printf("%d\n", strlen(&p + 1));     // 随机值
	//	printf("%d\n", strlen(&p[0] + 1));  // 5
//}


//int main()
//{
//	//二维数组
//	int a[3][4] = { 0 };
//	printf("%d\n", sizeof(a));           // 48
//	printf("%d\n", sizeof(a[0][0]));     // 某一元素：4
//	printf("%d\n", sizeof(a[0]));        // 16，a[0]是第一行这个一维数组的数组名，单独放在sizeof内部，a[0]表示第一个整个这个数组
//
//	// a[0]没有单独放在sizeof，以及没有取&，所以它表示第一行第一个元素地址，a[0]+1就是第一行第二个元素的地址
//	printf("%d\n", sizeof(a[0] + 1));    //4
//	printf("%d\n", sizeof(*(a[0] + 1))); // 4，第一行第二个元素
//
//	//虽然a是二维数组的地址，但是并没有单独放在sizeof内部，也没有取&
//	//a表示首元素的地址，二维数组首元素是它的第一行，a就是第一行的地址
//	//a+1就是跳过第一行，表示第二行的地址
//
//	printf("%d\n", sizeof(a + 1));         //4
//
//	//*（a + 1）是对第二行地址的解引用，拿到的是第二行
//	printf("%d\n", sizeof(*(a + 1)));      //16
//
//	//&a[0] 对第一行的数组名取地址，拿出的是第一行的地址
//	//&a[0]+1 得到的是第二行的地址
//	printf("%d\n", sizeof(&a[0] + 1));     //地址，4
//
//	//*(&a[0] + 1)第二行地址的解引用
//	printf("%d\n", sizeof(*(&a[0] + 1)));  //16
//
//	//a表示首元素的地址，就是第一行的地址
//	//*a就是对第一行地址解引用，拿到的是第一行
//	printf("%d\n", sizeof(*a));            // 16
//	printf("%d\n", sizeof(a[3]));          // 如果有第四行，其判断还是会按照初始化的int a[3][4] = { 0 }来判断;16
//}

//2024.4.18
//指针笔试题

//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//
//	//&a是数组指针，其类型是int(*)[5],&a+1跳过整个数组并取地址
//	//ptr是整型指针，类型为int*,ptr-1是跳过一个整型元素
//	int* ptr = (int*)(&a + 1);
//	printf("%d, %d", *(a + 1), *(ptr - 1)); // 2   5
//	return 0;
//}


//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p = (struct Test*)0x100000;
////假设p 的值为0x100000。 如下表表达式的值分别为多少？
////已知，结构体Test类型的变量大小是20个字节
//int main()
//{
//	//结构体指针p+1是跳过整个结构体，p+0x1 --->0x100000 + 20 = 0x100014
//	printf("%p\n", p + 0x1);
//
//	//将结构体指针p强转成无符号长整型，0x100000 + 1 = 0x100001
//	printf("%p\n", (unsigned long)p + 0x1);
//
//	//将结构体指针p强转成无符号int*,其+1跳过一个整型 0x100000 + 4 = 0x100004
//	printf("%p\n", (unsigned int*)p + 0x1);
//	return 0;
//}


//int main()
//{
//	int a[4] = { 1, 2, 3, 4 };
//	int* ptr1 = (int*)(&a + 1);
//	int* ptr2 = (int*)((int)a + 1);
//	//假设a = 0x0012ff40,则(int)a+1 = 0x0012ff41,再将其转换成int*得到ptr2
//	//内存存储方式（低地址-高地址）： 01 00 00 00 | 02 00 00 00 | 03 00 00 00 | 04 00 00 00 
//	//所以*ptr2则是访问到内存中的 00 00 00 | 02 ，小端存储读取后则是02 00 00 00
//
//	// ptr1[-1] --> *(ptr1 + (-1)) --> *(ptr-1),ptr1类型为int*,跳过一个整型大小，读取结果为00 00 00 04
//	printf("%x,%x", ptr1[-1], *ptr2);  // 4， 2000000
//	return 0;
//}


//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//逗号表达式，取最后一个作为结果，实际上是{1, 3, 5, 0, 0, 0}
//	int* p;
//	p = a[0];   //a[0]是第一行的数组名，但它没有单独放在sizeof内部，也没有取&，
//				//所以这里它表示首元素的地址，即a[0][0]的地址，&a[0][0]
//	printf("%d", p[0]);  //1   p[0] ---> *(p + 0) --> *p --> a[0][0]
//	return 0;
//}



//int main()
//{
//	int a[5][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
//	int(*p)[4];
//
//	// a --> int(*)[5]   p --> int(*)[4]
//	p = a;
//
//	//p[4][2] --> *(*(p+4)+2)  p的类型是int(*)[4]，p+1会一次跳过4个整型元素的, *(*(p+4)+2)表示具体某个元素值
//	//地址相减，得到的是他们之间的元素个数
//	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]); // -4(转换成补码FF FF FF FC) ，-4
//	//printf("%d ", p[4][2]);
//	return 0;
//}


// 2024.4.19 

//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1));
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));   // 10, 5
//	return 0;
//}


//int main()
//{
//	char* a[] = { "work","at","alibaba" };
// //char** pa 可以理解成：char*  *p,其中，*p表示p是一个指针， char*表示p指针指向的对象是char*类型
// //类似的，int *p 可以理解成：*p表示p是一个指针，int表示p指针指向的对象是int类型
//	char** pa = a;
//	pa++;
//	printf("%s\n", *pa);   //at 
//	return 0;
//}


//画图来分析这些指针内容
//int main()
//{
//	char* c[] = { "ENTER","NEW","POINT","FIRST" };
//	char** cp[] = { c + 3,c + 2,c + 1,c };
//	char*** cpp = cp;
//	printf("%s\n", **++cpp);         //++操作符直接会将cpp的值改变，++cpp --> cpp = cpp + 1,POINT
//	printf("%s\n", *-- * ++cpp + 3); // ER
//	printf("%s\n", *cpp[-2] + 3);    //ST
//	printf("%s\n", cpp[-1][-1] + 1); //EW
//	return 0;
//}


//int main()
//{
//	char arr[] = "abcdef";    //abcdef\0
//	char arr2[] = { 'b', 'i', 't' };
//
//
//	//函数原型：size_t strlen( const char *string );
//	//strlen()返回的是size_t无符号整型
//	int len = strlen(arr);
//	int len2 = strlen(arr2);
//	printf("%d %d", len, len2);
//	return 0;
//
//}

//模拟strlen()
//size_t my_strlen(const char* arr)
//{
//	assert(arr);
//	size_t count = 0;
//	while (*arr != '\0')
//	{
//		count++;
//		arr++;
//	}
//	return count;
//}
//
//int main()
//{
//	char arr[] = "abcdef";
//	int ret = my_strlen(arr);
//	printf("%d ", ret);
//	return 0;
//}


//函数原型：char *strcpy( char *strDestination, const char *strSource );
//拷贝\0前面的字符，连\0也一起拷贝



//int main()
//{
//	char name[20] = { 0 };
//	//strcpy(name, "zhang\0san");
//	//name = "zhangsan"; //error, name数组名是地址，地址是一个常量值，不能被赋值
//
//	char arr[] = { 'b', 'i', 't' };//无法预知\0的地方
//	strcpy(name, arr);
//	printf("%s", name);
//
//
//	const char* p = "abcdef";
//	char arr[] = "bit";
//	strcpy(p, arr);  //目标区域不可修改
//
//	return 0;
//}


//模拟strcpy
//char* my_strcpy(char* dest, const char* source)
//{
//	assert(dest && source);
//
//	char* start = dest;
//	while (*dest++ = *source++)
//	{
//		;
//	}
//	return start;
//}
//
//
//int main()
//{
//	char arr1[] = "abcdef";
//	char arr2[20] = { 0 };
//	my_strcpy(arr2, arr1);
//	printf("%s", arr2);
//	return 0;
//}


//字符串追加strcat(),函数原型：char *strcat( char *strDestination, const char *strSource );
//
//char* my_strcat(char* dest, const char* source)
//{
//	char* start = dest;
//	assert(dest && source);
//
//	//1.找到目标空间的末尾\0
//	while (*dest != '\0')
//	{
//		dest++;
//	}
//	//2.拷贝字符串
//	while (*dest++ = *source++)  //此判断将'\0'也赋值到dest后，循环才会停止
//	{
//		;
//	}
//	return start;
//}
//
//
//int main()
//{
//	char arr[50] = "hello";
//	//strcat(arr, arr);//自己给自己追加，库函数也不行
//	my_strcat(arr, "world");
//
//	printf("%s", arr);
//	return 0;
//
//}


//字符串比较函数：int strcmp( const char *string1, const char *string2 );
//int my_strcmp(const char* str1, const char* str2)
//{
//	assert(str1 && str2);
//	while (*str1 == *str2)
//	{
//		if (*str1 == '\0')
//			return 0;
//		str1++;
//		str2++;
//
//	}
//	if (*str1 > *str2)
//		return 1;
//	else
//		return -1;
//}
//int main()
//{
//	char arr[20] = "zhangsan";
//	char arr2[] = "zhangsanfeng";
//
//	//两个字符串比较相等，应该使用strcmp
//	//int ret = strcmp(arr, arr2);
//
//	int ret = my_strcmp(arr, arr2);
//
//	if (ret < 0)
//		printf("<\n");
//	else if (ret == 0)
//		printf("==\n");
//	else
//		printf(">\n");
//}


//长度受限制的字符串函数
//strncpy
//strncat
//strncmp

//int main()
//{
//	//strncpy函数原型：char *strncpy( char *strDest, const char *strSource, size_t count );
//	char arr1[20] = "abcdef";
//	char arr2[] = "hello world";
//	strncpy(arr1, arr2, 5);  //长度不够，则拷贝'\0'
//	printf("%s", arr1);      //hellof
//	return 0;
//}

//int main()
//{
//	//strncat函数原型：char *strncat( char *strDest, const char *strSource, size_t count );
//	char arr1[20] = "hello\0xxxxxx";
//	char arr2[] = "bit";
//	strncat(arr1, arr2, 6); //该追加几个就追加几个，追加完后会在补一个\0
//	printf("%s", arr1);
//	return 0;
//}


//int main()
//{
//	//strncmp函数原型:char *strncpy( char *strDest, const char *strSource, size_t count );
//	char arr[] = "abcdef";
//	char arr2[] = "abc";
//	int ret = strncmp(arr, arr2, 4);
//	if (ret == 0)
//		printf("==\n");
//	else if (ret < 0)
//		printf("<\n");
//	else
//		printf(">\n");
//
//}


//KMP算法
//这个算法也是用来实现在一个字符串查找子字符串的
//效率高，但实现难度大
//char* my_strstr(const char* str1, const char* str2)
//{
//	assert(str1 && str2);
//	const char* s1 = str1;    //
//	const char* s2 = str2;    //指向子串
//	const char* p = str1;
//	while (*p)
//	{
//		s1 = p;
//		s2 = str2;
//		while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
//		{
//			s1++;
//			s2++;
//
//		}
//		if (*s2 == '\0')
//		{
//			return (char*)p;
//		}
//		p++;
//
//	}
//	return NULL;
//}
//
//
//int main()
//{
//	//strstr查找子串的一个函数，函数原型：char *strstr( const char *string, const char *strCharSet );
//
//	char email[] = "ljx@vbitejiuyeke.com";
//	char substr[] = "jiuyeke.com";
//	//char* ret = strstr(email, substr);
//
//	char* ret = my_strstr(email, substr);
//
//	if (ret == NULL)
//		printf("字串不存在");
//	else
//	{
//		printf("%s", ret);
//	}
//	return 0;
//}




//strtok切割字符串：char * strtok ( char * str, const char * sep );

//int main()
//{
//	const char* sep = "@j";
//	char email[] = "abcdefb@@tuyigjdk";
//	char cp[30] = { 0 };
//
//	strcpy(cp, email);
//	char* ret = NULL;
//	for (ret = strtok(cp, sep); ret != NULL; ret = strtok(NULL, sep))
//	{
//		printf("%s\n", ret);
//	}


	//strtok函数会改变被操作的字符串，所以应该先拷贝一份字符串
	// strtok函数的第一个参数不为 NULL ，函数将找到str中第一个标记，strtok函数将保存它在字符串中的位置
	//abcdefb\0tuyigjdk
	//char* ret = strtok(cp, sep);
	//printf("%s\n", ret);   //abcdefb

	//abcdefb\0tuyig\0dk
	 // strtok函数的第一个参数为 NULL ，函数将在同一个字符串中被保存的位置开始，查找下一个标记
	 //ret = strtok(NULL, sep);  //传NULL，使用static来保存之前的位置来实现
	 //printf("%s\n", ret);  // tuyig

	 //ret = strtok(NULL, sep);
	 //printf("%s\n", ret);  // dk

//	return 0;
//}


//strerror错误码
//int main()
//{
//	//printf("%s\n", strerror(0));
//	//printf("%s\n", strerror(1));
//	//printf("%s\n", strerror(2));
//	//printf("%s\n", strerror(3));
//	//printf("%s\n", strerror(4));
//	//printf("%s\n", strerror(5));
//
//	//errno - C语言设置的一个全局的错误码存放的变量
//	FILE* pf = fopen("test.txt", "r");
//	if (pf == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//	else
//	{
//
//	}
//	return 0;
//
//}


//字符分类函数

//int main()
//{
//	int a = isspace('w'); //判断字符串是否含有空白字符,如空格、\t、\b，若是，则返回非零；若不是，则返回0
//	printf("%d\n", a);
//
//
//	int b = isdigit('1');//判断字符串是否为数字,若是，则返回非零；若不是，则返回0
//	printf("%d\n", b);
//	return 0;
//}


//字符转换
//int main()
//{
//	printf("%c\n", tolower('W'));
//	printf("%c\n", toupper('W'));
//
//	return 0;
//}
//

//内存拷贝memcpy,可以拷贝多种类型的数据(int, float, struct等)
//字符串拷贝使用strcpy()
//void* my_memcpy(void* dest, const void* src, size_t num)
//{
//	assert(dest && src);
//	void* ret = dest;
//
//	while (num--)
//	{
//		*(char*)dest = *(char*)src;
//		dest = (char*)dest + 1;
//		src = (char*)src + 1;
//	}
//
//	return ret;
//}

//memcpy 负责拷贝两块独立空间中的数据,不用来处理重叠的内存之间的数据拷贝的
//怎么实现重叠内存拷贝 memmove
//memcpy()函数原型：void *memcpy( void *dest, const void *src, size_t count ); 参数size_t count为字节数
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
//	int arr2[10] = { 0 };
//	//memcpy(arr2, arr, 28);
//	my_memcpy(arr2, arr, 32);
//
//
//	//float arr3[5] = { 1.0, 2.0, 3.0, 4.0, 5.0 };
//	//float arr4[10] = { 0.0 };
//	//memcpy(arr4, arr3, 20);
//
//
//	return 0;
//}


//2024.4.21
//memmove函数原型void *memmove( void *dest, const void *src, size_t count );
//memmove实现重叠内存拷贝 

//void* my_memmove(void* dest, const void* src, size_t num)
//{
//	assert(dest && src);
//	void* ret = dest;
//	if (dest < src)
//	{
//		//前->后拷贝
//		while (num--)
//		{
//			*(char*)dest = *(char*)src;
//			dest = (char*)dest + 1;
//			src = (char*)src + 1;
//		}
//	}
//	else
//	{
//		//后->前拷贝
//		while (num--)//num--原地操作，会改变num的值
//		{
//			*((char*)dest + num) = *((char*)src + num);
//		}
//	}
//	return ret;
//}
//
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	//memmove(arr + 2, arr, 20);
//	//memcpy(arr + 2, arr, 20);  //memcpy也实现了重叠的要求
//	//my_memmove(arr + 2, arr, 20);
//	my_memmove(arr, arr + 2, 20);
//
//	//1 2 1 2 3 4 5 8 9 10
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//
//	}
//	return 0;
//}


//2024.4.26
// memcmp函数原型：int memcmp( const void *buf1, const void *buf2, size_t count );

//int main()
//{
//	int arr1[] = { 1, 2, 3, 4, 5, 6 }; // 01 00 00 00 02 00 00 00 03 00 00 00
//	int arr2[] = { 1, 3, 2 };		   // 01 00 00 00 03 00 00 00 02 00 00 00
//	int ret = memcmp(arr1, arr2, 12);    //比较前12个字节的内容，如果不相等，则提前返回-1
//	printf("%d\n", ret);
//	return 0;
//
//}

//memset函数原型：void *memset( void *dest, int c, size_t count );
//int main()
//{
//	/*char arr[] = "hello, bit";
//	memset(arr, 'x', 5);
//	memset(arr + 7, 'x', 3);
//	printf("%s", arr);*/
//
//
//	int arr[10] = { 0 };
//	memset(arr, 1, 40);              //memset是以字节为单位来设置指定数值, 即11 11 11 11.....
//	for (int i = 0; i < 10; i++)
//	{
//		printf("%d\n", arr + i);
//	}
//	return 0;
//}



//2024.5.7
//小乐乐喜欢数字，尤其喜欢0和1。他现在得到了一个数，想把每位的数变成0或1.如果某一位是奇数，就把它变成1，
//如果是偶数，那么就把它变成0。请你回答他最后得到的数是多少。

//输入:222222
//输出:0

//输入：123
//输出：101

//int main()
//{
//	int input = 0;
//	int sum = 0;
//	//输入
//	scanf("%d", &input);
//	int i = 0;
//	while (input)
//	{
//		int bit = input % 10;  //把每一位取出来
//		if (bit % 2 == 1)     // 判断那个位是否为奇数
//		{
//			sum += 1 * pow(10, i);   // 幂运算
//			i++;
//		}
//		else
//		{
//			sum += 0 * pow(10, i);
//			i++;
//		}
//		input /= 10;
//	}
//	printf("%d\n", sum);
//	return 0;
//
//}


// 带空格直角三角形图案
//    *
//   **
//  ***
// ****
//*****

//int main()
//{
//	int n = 0;
//	while (scanf("%d", &n) == 1)
//	{
//		int i = 0;
//		int j = 0;
//		for (i = 0; i < n; i++)
//		{
//			for (j = 0; j < n; j++)
//			{
//				if (i + j < n - 1)
//					printf(" ");
//				else
//					printf("*");
//			}
//			printf("\n");
//		}
//	}
//}

//KiKi非常喜欢网购，在一家店铺他看中了一件衣服，他了解到，如果今天是“双11”(11月11日)
//则这件衣服打7折，“双12”(12月12日)则这件衣服打8折，
//如果有优惠券可以额外减50元(优惠券只能在双11或双12使用)，
//求KiKi最终所花的钱数。


//输入描述 :
//一行，四个数字，第一个数表示小明看中的衣服价格，第二和第三个整数分别表示当天的月份、当天的日期、
//第四个整数表示是否有优惠券(有优惠券用1表示，无优惠券用0表示)。注 : 输入日期保证只有“双11“和“双12”。


//输出描述 :
//一行，小明实际花的钱数(保留两位小数)。(提示 : 不要指望商家倒找你钱)

//int main()
//{
//	//输入
//	double price = 0.0;
//	int m = 0;
//	int d = 0;
//	int flag = 0;
//	scanf("%lf %d %d %d", &price, &m, &d, &flag);
//	//计算
//	if (m == 11 && d == 11)
//	{
//		price = price * 0.7 - flag * 50;
//	}
//	else if (m == 12 && d == 12)
//	{
//		price = price * 0.8 - flag * 50;
//
//	}
//	if (price < 0.0)
//		printf("%.2lf\n", 0);
//	else
//	{
//		printf("%.2lf", price);
//	}
//	return 0;
//}

//int main()
//{
//	// char -128 ~ 127
//	// unsigned char 0~255
//	unsigned char a = 200;
//	// 00000000 00000000 00000000 11001000
//	// 11001000 -a 截断
//	unsigned char b = 100;
//	// 00000000 00000000 00000000 01100100
//	// 01100100 -b 截断
//
//	unsigned char c = 0;
//	c = a + b;
//	//整型提升
//	// 00000000 00000000 00000000 11001000
//	// 00000000 00000000 00000000 01100100
//	// 00000000 00000000 00000001 00101100 -> a+b
//	// 00101100 -c 截断
//	// 补零
//	// 00000000 0000000  00000000 00101100(正数，原反补码相同,即44)
//	printf("%d %d", a + b, c);  // 300 44
//	return 0;
//}

//int main()
//{
//	unsigned int a = 0x1234;   //0x 00 00 12 34
//	unsigned char b = *(unsigned char*)&a;     //解引用后，只能访问一个字节
//	printf("%x", b);    //小端字节序，34
//	return 0;
//}

// 2024.5.9
//题目名称:猜名次
// 
//题目内容 :
//5位运动员参加了10米台跳水比赛，有人让他们预测比赛结果 :
//A选手说 : B第二，我第三;
//B选手说:我第二，E第四;
//C选手说:我第一，D第二;
//D选手说:C最后，我第三;
//E选手说:我第四，A第一:

//比赛结束后，每位选手都说对了一半，请编程确定比赛的名次。

//int main()
//{
//	int a = 0;
//	int b = 0;
//	int c = 0;
//	int d = 0;
//	int e = 0;
//	for (a = 1; a <= 5; a++)
//	{
//		for (b = 1; b <= 5; b++)
//		{
//			for (c = 1; c <= 5; c++)
//			{
//				for (d = 1; d <= 5; d++)
//				{
//					for (e = 1; e <= 5; e++)
//					{
//						if (((b == 2) + (a == 3) == 1)
//							&& ((b == 2) + (e == 4) == 1)
//							&& ((c == 1) + (d == 2) == 1)
//							&& ((c == 5) + (d == 3) == 1)
//							&& ((e == 4) + (a == 1) == 1))
//						{
//							if (a * b * c * d * e == 120)  //过滤下重名次的结果
//								printf("a=%d, b=%d, c=%d, d=%d, e=%d", a, b, c, d, e);
//						}
//					}
//				}
//			}
//		}
//	}
//	return 0;
//} 


//题目名称:猜凶手
//
//题目内容 :
//日本某地发生了一件谋杀案，警察通过排查确定杀人凶手必为4个嫌疑犯的一个
//以下为4个嫌疑犯的供词 :
//A说 :不是我。
//B说 : 是C。
//C说 : 是D。
//D说 : C在胡说
//
//已知3个人说了真话，1个人说的是假话。

//int main()
//{
//	int killer = 0;
//	for (killer = 'a'; killer < 'd'; killer++)
//	{
//		//判断
//		if ((killer != 'a') + (killer == 'c')
//			+ (killer == 'd') + (killer != 'd') == 3)
//		{
//			printf("%c\n", killer);
//		}
//	}
//	return 0;
//}


//题目名称:杨辉三角
//
//题目内容 :
//在屏幕上打印杨辉三角。
//
//1
//1 1
//1 2 1
//1 3 3 1
//.....

//int main()
//{
//	int arr[10][10] = { 0 };
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < 10; i++)
//	{
//		for (j = 0; j <= i; j++)
//		{
//			if (j == 0)
//				arr[i][j] = 1;
//			if (i == j)
//				arr[i][j] = 1;
//			if (i >= 2 && j >= 1)
//			{
//				arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
//			}
//
//		}
//	}
//	for (i = 0; i < 10; i++)
//	{
//		for (j = 0; j <= i; j++)
//		{
//			printf("%3d", arr[i][j]);
//
//		}
//		printf("\n");
//	}
//	return 0;
//
//}

//实现一个函数，可以左旋转字符串的k个字符
//输入：abcdef,k=2
//输出：cdefab
//void left_rotate(char arr[], int k)
//{
//	int i = 0;
//	int len = strlen(arr);
//	for (i = 0; i < k; i++)
//	{
//		//旋转一个字符
//		char tmp = arr[0];
//		int j = 0;
//		for (j = 0; j < len - 1; j++)
//		{
//			arr[j] = arr[j + 1];
//
//		}
//		arr[len - 1] = tmp;
//	}
//}

//void reverse(char* left, char* right)
//{
//	assert(left && right);
//	while (left < right)
//	{
//		char tmp = *left;
//		*left = *right;
//		*right = tmp;
//		left++;
//		right--;
//	}
//}

//技巧性强
//void left_rotate(char arr[], int k)
//{
//	int len = strlen(arr);
//	k %= len;
//	reverse(arr, arr + k - 1);//左
//	reverse(arr + k, arr + len - 1);//右
//	reverse(arr, arr + len - 1);//整体
//}


//int main()
//{
//	char arr[] = "abcdef";
//	int k = 0;
//	scanf("%d", &k);
//	left_rotate(arr, k);
//	printf("%s\n", arr);
//	return 0;
//}


//杨氏矩阵
//有一个数字矩阵，矩阵的每行从左到右是递增的，矩阵的每列从上到下是递增的
//请编写程序在这样的矩阵中查找某个数字是否存在。
//要求:时间复杂度小于0(N);
//1 2 3
//4 5 6
//6 7 8


//int find_num(int arr[3][3], int r, int c, int k) //找不找得到，没有返回下标
//{
//	int x = 0;
//	int y = c - 1;
//	while (x <= r - 1 && y >= 0)
//	{
//		if (k < arr[x][y])  //选取右上角的元素进行判断
//		{
//			y--;
//		}
//		else if (k > arr[x][y])
//		{
//			x++;
//		}
//		else
//		{
//			return 1;
//		}
//	}
//	return 0;//找不到
//}



//第一种返回下标的方法（使用结构体）
//struct Point
//{
//	int x;
//	int y;
//}; //建立结构体，为了能够返回找到的那个数的下标，返回两个下标值
//
//struct Point find_num(int arr[3][3], int r, int c, int k) //找不找得到，没有返回下标
//{
//	int x = 0;
//	int y = c - 1;
//	struct Point p = { -1, -1 };
//	while (x <= r - 1 && y >= 0)
//	{
//		if (k < arr[x][y])  //选取右上角的元素进行判断
//		{
//			y--;
//		}
//		else if (k > arr[x][y])
//		{
//			x++;
//		}
//		else
//		{
//			p.x = x;
//			p.y = y;
//			return p;
//		}
//	}
//	return p;//找不到
//}

//第二种返回下标的方法（指针,传指针可以修改数值）
//返回型参数
//int find_num(int arr[3][3], int* px, int* py, int k) //二维数组作为参数传递给函数，也可以写成 int (*arr)[3]数组指针的形式
//{
//	int x = 0;
//	int y = *py - 1;
//	while (x <= *px - 1 && y >= 0)
//	{
//		if (k < arr[x][y])  //选取右上角的元素进行判断
//		{
//			y--;
//		}
//		else if (k > arr[x][y])
//		{
//			x++;
//		}
//		else
//		{
//			*px = x;
//			*py = y;
//			return 1;
//		}
//	}
//	*px = -1;
//	*py = -1;
//	return 0;//找不到
//}
//
//int main()
//{
//	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
//	int k = 0;
//	scanf("%d", &k);
//	//struct Point ret = find_num(arr, 3, 3, k);
//	//printf("%d %d\n", ret.x, ret.y);
//
//
//	int x = 3;
//	int y = 3;
//	int ret = find_num(arr, &x, &y, k);
//
//
//	if (ret == 1)
//	{
//		printf("%d %d\n", x, y);
//	}
//	else
//	{
//		printf("找不到\n");
//	}
//	return 0;
//
//}



//2024.6.1
//题目名称:字符串旋转结果

//题目内容 :
//写一个函数，判断一个字符串是否为另外一个字符串旋转之后的字符串,
//例如 : 给定S1 = AABCD和s2 = BCDAA，返回1
// 给定s1 = abcd和S2 = ACBD，返回0.

//AABCD左旋一个字符得到ABCDA
//AABCD左旋两个字符得到BCDAA
//AABCD右旋一个字符得到DAABC


//穷举法
//int is_left_move_1(char arr1[], char arr2[])
//{
//	int len = strlen(arr1);
//	int i = 0;
//	for (i = 0; i < len; i++)
//	{
//		char tmp = arr1[0];
//		int j = 0;
//		//旋转字符
//		for (j = 0; j < len - 1; j++)
//		{
//			arr1[j] = arr1[j + 1];
//
//		}
//		arr1[len - 1] = tmp;
//
//		//判断两个字符串是否相同
//		if (strcmp(arr2, arr1) == 0)
//		{
//			return 1;
//		}
//	}
//	return 0;
//}
//
//int is_left_move_2(char arr1[], char arr2[])
//{
//	int len1 = strlen(arr1);
//	int len2 = strlen(arr2);
//	if (len1 != len2)
//		return 0;
//
//	strncat(arr1, arr1, len1);//多复制一份字符串得到的长字符串包含了所有旋转后的字符串的情况
//	char* ret = strstr(arr1, arr2);
//	if (ret == NULL)
//	{
//		return 0;
//	}
//	else
//	{
//		return 1;
//	}
//}
//
//int main()
//{
//	char arr1[20] = "abcdef";
//	char arr2[] = "cdefab";
//	//判断arr2中的字符串是否可以通过arr1中的字符串旋转得到
//	//int ret = is_left_move_1(arr1, arr2);
//	int ret = is_left_move_2(arr1, arr2);
//	if (ret == 1)
//	{
//		printf("ok");
//	}
//	else
//	{
//		printf("no");
//	}
//	return 0;
//}


//int main()
//{
//	int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1));
//	printf(" % d, % d", *(ptr1 - 1), *(ptr2 - 1));  //1, 6
//	return 0;
//}

//二维数组int arr[2][5]的数组名arr表示的是第一行的地址，即一维数组的地址(数组指针)，接收参数的类型可以是int (*arr)[5]


//矩阵转置
//输入描述:
//第一行包含两个整数n和m，表示一个矩阵包含n行m列，用空格分隔。
// (1≤n≤10, 1≤m≤10)从2到n + 1行，每行输入m个整数(范围 - 231~231 - 1)，用空格分隔，共输入n * m个数，表示第一个矩阵中的元素。

//输出描述 :输出m行n列，为矩阵转置后的结果。每个数后面有一个空格。
//输入 : 2 3
//1 2 3
//4 5 6

//输出 : （其实就是输入的数组按列输出）
//1 4
//2 5
//5 6


//int main()
//{
//	int n = 0;
//	int m = 0;
//	scanf("%d%d", &n, &m);
//	//int arr[n][m];//C99中的变长数组（VS不支持），变长数组不能初始化
//	int arr[10][10] = { 0 };
//	int i = 0;
//	int j = 0;
//	//输入
//	for (i = 0; i < n; i++)
//	{
//		for (j = 0; j < m; j++)
//		{
//			scanf("%d", &arr[i][j]);
//		}
//	}
//
//
//	//输出
//	//列
//	for (i = 0; i < m; i++)
//	{
//		//行
//		for (j = 0; j < n; j++)
//		{
//			printf("%d ", arr[j][i]);
//		}
//		printf("\n");
//	}
//	return 0;
//}


//上三角矩阵的判定
//描述
//KiKi想知道一个n阶方矩是否为上三角矩阵，请帮他编程判定。
//上三角矩阵即主对角线以下的元素都为0的矩阵，主对角线为从矩阵的左上角至右下角的连线。

//输入描述 :第一行包含一个整数n，表示一个方阵包含n行n列，用空格分隔。
//(1≤n≤10)从2到n + 1行，每行输入n个整数(范围 - 231~231 - 1)，用空格分隔，共输入n * n个数。

//输出描述 :一行，如果输入方阵是上三角矩阵输出"YES"并换行，否则输出"NO"并换行。
//输入 : 3
//1 2 3
//0 4 5
//0 0 6
//输出 : YES


//int main()
//{
//	int n = 0;
//	//int arr[n][n];//C99支持变长数组
//	int arr[10][10] = { 0 };
//	int i = 0;
//	int j = 0;
//	int flag = 1;//是上三角矩阵
//	scanf("%d", &n);
//	for (i = 0; i < n; i++)
//	{
//		for (j = 0; j < n; j++)
//		{
//			scanf("%d", &arr[i][j]);
//		}
//	}
//
//	//判断
//	for (i = 0; i < n; i++)
//	{
//		for (j = 0; j < i; j++)//j < i:找到三角的位置进行判断
//		{
//			if (arr[i][j] != 0)
//			{
//				flag = 0;
//				goto end;
//			}
//		}
//	}
//end://如果没有执行到goto这句代码时，并且两层for循环已经执行完，那么会继续顺序执行end以下部分的代码，
//	//而不是只有执行goto语句才会执行end以下的代码
//	if (flag == 0)
//		printf("NO");
//	else
//	{
//		printf("YES");
//	}
//	return 0;
//}

//有序序列的判断
//描述：输入一个整数序列，判断是否是有序序列，有序，指序列中的整数从小到大排序或者从大到小排序(相同元素也视为有序)。
//数据范围 : 3≤n≤50 序列中的值都满足1≤val≤100
//输入描述 :第一行输X一个整数N(3≤N≤50)。
//第二行输入N个整数，用空格分隔N个整数。

//输出描述 :输出为一行，如果序列有序输出sorted，否则输出unsorted。

//输入 : 5
//1 6 9 22 30
//输出 : sorted

//int main()
//{
//	int n = 0;
//	int arr[50] = { 0 };
//	scanf("%d", &n);
//	int i = 0;
//	int flag1 = 0;
//	int flag2 = 0;
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//		if (i > 0)
//		{
//			if (arr[i] > arr[i - 1])
//			{
//				flag1 = 1; //flag1 = 1表示升序
//			}
//			else if (arr[i] < arr[i-1])
//			{
//				flag2 = 1; //flag2 = 1表示降序
//			}
//			else//arr[i] == arr[i-1]不做任何事情
//			{
//				;
//			} 
//		}
//	}
//	if (flag1 + flag2 <= 1)//只有一个为1，另一个为0时才是有序序列
//		printf("sorted!");
//	else
//		printf("unsorted!");
//
//	return 0;
//}


//结构体类型的定义

//学生
//struct Stu
//{
//	char name[20];
//	int age;
//
//};

//匿名结构体:只能用一次
//struct
//{
//	char name[20];
//	int a;
//	
//}s1;

//err
//struct Node
//{
//	int data;
//	struct Node next; //包含同类型的结构体是err
//};
//
//
//
//struct Node
//{
//	int data;
//	struct Node* next; //包含同类型的结构体指针
//};
//
//int main()
//{
//	int size = sizeof(struct Node);
//	printf("%d", size);
//	return 0;
//}



//err
//typedef struct
//{
//	int data;
//	Node* next;//编译器不认识这个标识符
//}Node;
//
//
////correct
//typedef struct Node
//{
//	int data;
//	struct Node* next;
//}Node;
//
//int main()
//{
//	//以下两种语法意思相同
//	struct Node n1;
//	Node n2;
//}


//结构体的声明和初始化
//struct Point
//{
//	int x;
//	int y;
//}p1 = { 2, 3 };
//
//struct score
//{
//	int n;
//	char ch;
//};
//
//struct Stu
//{
//	char name[20];
//	int age;
//	struct score s;
//};
//
//
//int main()
//{
//	struct Point p2 = { 4, 5 };
//	struct Stu s1 = { "zhangsan", 20, {100, 'q'} };
//	printf("%s %d %d %c\n", s1.name, s1.age, s1.s.n, s1.s.ch);
//	return 0;
//}

//结构体内存对齐（面试、笔试较多）
//struct S1
//{
//	char c1; // 1
//	int age; // 4
//	char c2; // 1
//};
//
//struct S2
//{
//	char c1; // 1
//	char c2; // 1
//	int age; // 4
//};
//
//struct S3
//{
//	double d;
//	char c;
//	int i;
//};
//struct S4
//{
//	char c1;
//	struct S3 s3;
//	double d;
//};


//只有VS有默认对齐数（为8），gcc是没有默认对齐数，所以gcc的结构体大小就是各成员变量大小的总和
//#include <stddef.h>
//int main()
//{
//	//printf("%d\n", sizeof(struct S1)); //12  
//	//printf("%d\n", sizeof(struct S2)); // 8
//
//	printf("%d\n", sizeof(struct S3));
//	printf("%d\n", sizeof(struct S4));
//
//	//计算某个变量到0地址处的偏移量
//	//宏：offsetof(type, member)
//	//printf("%d\n", offsetof(struct S1, c1));
//	//printf("%d\n", offsetof(struct S1, age));
//	//printf("%d\n", offsetof(struct S1, c2));
//
//	//printf("%d\n", offsetof(struct S2, c1));
//	//printf("%d\n", offsetof(struct S2, age));
//	//printf("%d\n", offsetof(struct S2, c2));
//
//	return 0;
//}


//#pragma once 
//头文件中使用，功能是：防止头文件被多次引用

//#pragma pack(1) //修改默认对齐数
//struct S
//{
//	int i;
//	double d;
//};
//#pragma pack() //恢复默认值
//
//
//int main()
//{
//	printf("%d\n", sizeof(struct S));
//	return 0;
//}



//结构体传参
//struct S
//{
//	int data[1000];
//	int num;
//
//};
//
//void print1(struct S ss)
//{
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		printf("%d ", ss.data[i]);
//
//	}
//	printf("%d\n", ss.num);
//}
//
//void print2(struct S* ps)
//{
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		printf("%d ", ps->data[i]);
//
//	}
//	printf("%d\n", ps->num);
//}
//
//int main()
//{
//	struct S s = { {1, 2, 3}, 100 };
//	print1(s); //传值
//	print2(&s); //传址（首选）
//
//	return 0;
//}


//位段：帮助减少空间
//struct A
//{
//	//先开辟4个字节-32位
//	int _a : 2;    //_a只占2个bit
//	int _b : 5;    //_b只占5个bit
//	int _c : 10;  //_c只占10个bit
//
//	//再开辟4个字节
//	int _d : 30;  //_d只占30个bit
//
//};
//
//int main()
//{
//	printf("%d", sizeof(struct A));  // 8
//	return 0;
//}


//位段的存储方式(网络通信：数据包，底层代码就用到了位段)
//struct S
//{
//	//结论：如果位数不够，则会以浪费的形式来重新开辟新的空间
//	char a : 3;
//	char b : 4;
//	char c : 5;
//	char d : 4;
//
//};
//
//int main()
//{
//	struct S s = { 0 };
//	printf("%d\n", sizeof(struct S));
//	//内存存放形式62 03 04， 即01100010 00000011 00000100
//	s.a = 10; // 1010-->010
//	s.b = 12; // 1100
//	s.c = 3;  // 0011
//	s.d = 4;  // 0100
//
//	return 0;
//}



//2024.6.3

//enum day
//{
//	Mon,//枚举常量，默认从0开始，也可以修改
//	Tus,//1
//	Wed,//2
//	Thur,//3
//	Fri,//4
//	Sat,//5
//	Sun//6
//};


//enum day
//{
//	Mon = 1,//枚举常量
//	Tus,//2
//	Wed,//3
//	Thur,//4
//	Fri,//5
//	Sat,//6
//	Sun//7
//};

/*
枚举用途:增加可读性，如

enum option
{
	EXIT,
	ADD,
	DEL,
	SHOW,
	MODIFY,
	SORT,
	SEARCH

};

switch (input)
{
case ADD:
case DEL:
case SHOW:
case MODIFY:
case SORT:
case SEARCH:
}
而不是
switch (input)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
}
*/

//int main()
//{
//	enum day d = Fri;
//	printf("%d\n", Mon);
//	printf("%d\n", Tus);
//	printf("%d\n", Wed);
//	printf("%d\n", Thur);
//	printf("%d\n", Fri);
//	printf("%d\n", Sat);
//	printf("%d\n", Sun);
//	return 0;
//}

//enum Color
//{
//	RED = 1,
//	GREEN = 2,
//	BLUE = 3
//
//};
//
//int main()
//{
//	enum Color c = GREEN;
//	printf("%d", c);
//	return 0;
//}


//共用体 
//union Un
//{
//	int a;
//	char c;
//};
//
//int main()
//{
//	union Un u;
//	printf("%zu\n", sizeof(u));
//	printf("%p\n", &u);   //010FF6F8
//	printf("%p\n", &u.a); //010FF6F8
//	printf("%p\n", &u.c); //010FF6F8
//	return 0;
//}


//union Un  //共用体大小至少为最大成员的大小
//{
//	int a;
//	char c;
//};
//
//int main()
//{
//	union Un u;
//	u.a = 0x11223344;
//	u.c = 0x77;
//	return 0;
//
//}



//判断一个机器是大端字节序还是小端字节序

//int check_sys(int a)
//{
//	if (1 == *(char*)&a)
//		return 1;
//	else
//		return 0;
//}

//这种方法很巧妙
//int check_sys()
//{
//	union //匿名结构体，只需要用一次
//	{
//		int a;
//		char c;
//	}u;
//	u.a = 1;
//	return u.c;
//}
//
//int main()
//{
//	int a = 1;  //0x 00 00 00 01
//	//int ret = check_sys(a);
//	int ret = check_sys();
//
//	if (ret == 1)
//	{
//		printf("小端\n");
//	}
//	else
//	{
//		printf("大端\n");
//	}
//	return 0;
//
//}

//共用体其实也有内存对齐的概念
//union Un
//{
//	char a[5]; // 1 8 1 他的对齐数其实就是char， 1个字节 
//	int i;     // 4 8 4
//
//};
//
//int main()
//{
//	printf("%zu", sizeof(union Un));//8字节
//	return 0;
//}



//2024.6.5
//动态内存管理

//int main()
//{
//	int arr[10] = { 0 };            //在栈区实现的
//	//动态内存管理
//	//int* p = (int*)malloc(40);    //在堆区实现的
//	int* p = (int*)malloc(INT_MAX); 
//
//	if (p == NULL)
//	{
//		printf("%s", strerror(errno));
//		return 1;
//	}
//	//使用
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		*(p + i) = i;
//	}
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//
//	//没有free
//	//并不是说内存空间就不回收了
//	//当程序退出的时候，系统会自动回收内存空间的
//
//	//free写法
//	free(p);
//	p = NULL;
//	return 0;
//}


//int main()
//{
//	while (1)
//	{
//		malloc(1);
//	}
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int* p = &a;
//
//	free(p);   //报错，动态分配的内存才能用free()来释放
//	p = NULL;
//	return 0;
//}

//2024.6.9
//int main()
//{
//	int* p = NULL;
//	free(p);   //free掉null的内存空间操作，free是什么事情都没干
//	return 0;
//}


//开辟10个整型的空间

//int main()
//{
//	int* p = (int*)calloc(10, sizeof(int));   //calloc()函数会先初始化内存的内容为0，再返回地址
//	if (p == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//
//	free(p);
//	p = NULL;
//	return 0;
//}


//int main()
//{
//	int* p = malloc(40);
//	if (p == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//	//使用
//	// 1 2 3 4 5 6 7 8 9 10
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		*(p + i) = i + 1;
//	}
//
//	//扩容
//	//发现内存不够用，想扩容，从原来的40字节扩容到80字节
//	//realloc()使用有可能发生以下两种情况：
//	//1.可以在原先的地址直接追加要求的字节数，返回原先的地址
//	//2.在原先的地址追加新的字节数发现会覆盖其他内存的内容，
//	//这时候该函数会重新找到能够放得下80字节的内存空间，释放掉原先地址指向的内容，然后返回新的地址
//	int * ptr = (int *)realloc(p, 80);  
//
//	if (ptr != NULL)
//	{
//		p = ptr;
//	}
//
//	//使用
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//	free(p);
//	p = NULL;
//	return 0;
//}


//int main()
//{
//	realloc(NULL, 40);//等价于malloc(40)
//	return 0;
//}


//常见动态内存管理的错误

//1.对NULL指针的解引用操作
//int main()
//{
//	int* p = (int*)malloc(40);
//	if (p == NULL)
//	{
//		return 1;
//	}
//	*p = 20;  //若没有先判断p是否为NULL,直接解引用则会有可能出现报错
//	return 0;
//}

//2.对动态开辟空间的越界访问
//int main()
//{
//	int* p = (int*)malloc(40);
//	if (p == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//
//	int i = 0;
//	for (i = 0; i <= 10; i++)  //越界访问
//	{
//		p[i] = i;
//	}
//	free(p);
//	p = NULL;
//	return 0;
//}

//3.对非动态开辟内存使用free释放
//int main()
//{
//	int a = 10;
//	int* p = &a;
//	free(p);
//}


//4.使用free释放一块动态开辟内存的一部分
//int main()
//{
//	int* p = (int*)malloc(100);
//	p++;
//	free(p);
//}

//5.对同一块动态内存多次释放
//int main()
//{
//	int* p = (int*)malloc(100);
//	free(p);
//	free(p);
//}

//6.动态开辟内存忘记释放（内存泄漏）
//void test()
//{
//	int* p = (int*)malloc(100);
//	if (NULL != p)
//	{
//		*p = 20;
//	}
//}
//
//int main()
//{
//	test();
//	while (1);
//}



//面试题
//void GetMemory(char* p)
//{
//	p = (char*)malloc(100);
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(str);             //函数执行完，p销毁了，内存没有释放导致泄露
//	strcpy(str, "hello world"); //str依然是NULL，解引用时会崩溃
//	printf(str);
//}

//应修改如下
//void GetMemory(char** p)
//{
//	*p = (char*)malloc(100);
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(&str);
//	str存放的是动态内存开辟的100字节的地址
//	strcpy(str, "hello world"); //str依然是NULL，解引用时会崩溃
//	printf(str);
//	释放
//	free(str);
//	str = NULL;
//}
//
//int main()
//{
//	Test();
//	char* str = "Hello,world!\n";
//	printf("Hello,world!\n");
//	printf(str);
//	printf("%s\n", str);
//	return 0;
//}


//int* f1(void)
//{
//	int x = 10;
//	return (&x);  //函数返回，x变量会销毁，该指针变成野指针
//}
//
//int* f2(void)
//{
//	int* ptr;    //指针不初始化，指向的内容是不确定的，野指针
//	*ptr = 10;
//	return ptr;
//}

//int main(int argc, char* argv[])
//{
//	long i;
//	long a[16];
//	for (i = 0; i <= 17; i++)
//	{
//		a[i] = 0;
//		printf("%d", i);
//	}
//	return 0;
//}


//char* GetMemory(void)
//{
//	char p[] = "hello world";
//	return p;  //函数一旦执行完，p[]将会销毁，p成为了野指针           
//}
//
//
//void Test(void)
//{
//	char* str = NULL;
//	str = GetMemory();
//	printf(str);  //打印的内容是随机的
//}
//
//int main()
//{
//	Test();
//	return 0;
//}


//void Test(void)
//{
//	char* str = (char*)malloc(100);
//	strcpy(str, "hello");
//	free(str); //释放掉了str，但其值并不为NULL，是随机值        
//	if (str != NULL)
//	{
//		strcpy(str, "world");  //str是野指针
//		printf(str);
//	}
//}
//
//int main()
//{
//	Test();
//	return 0;
//}


//2024.6.10
//描述：
//小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数，
//但是他竟然不会求两个正整数的最大公约数与最小公倍数之和，请你帮助他解决这个问题。

//输入描述 :
//每组输入包含两个正整数n和m。(1≤n≤109，1≤m≤109)

//输出描述 :
//对于每组输入，输出一个正整数，为n和m的最大公约数与最小公倍数之和。


//输入 : 10 20
//输出 : 30

//复杂度太高
//int main()
//{
//	int n = 0;
//	int m = 0;
//	while (scanf("%d %d", &n, &m) == 2)
//	{
//		int min = n < m ? n : m;
//		int max = n > m ? n : m;
//		int i = min; //最大公约数，一次减一
//		int j = max; //最大公倍数，一次加一
//
//
//		while (1)
//		{
//			if (n % i == 0 && m % i == 0)
//			{
//				break;
//			}
//			i--;
//		}
//
//		while (1)
//		{
//			if (j % n == 0 && j % m == 0)
//			{
//				break;
//			}
//			j++;
//		}
//
//		printf("%d\n", i + j);
//
//	}
//	return 0;
//}

//辗转相除法
//int main()
//{
//	int n = 0;
//	int m = 0;
//	while (scanf("%d %d", &n, &m) == 2)
//	{
//		int i = n;
//		int j = m;
//		int r = 0;
//		while (r = i % j) //当r为0时，j就是最大公约数
//		{
//			i = j;
//			j = r;
//		}
//
//		//m * n / j //该值为最小公倍数
//		printf("%d\n", m * n / j + j);
//
//	}
//	return 0;
//}



//描述
//KiKi学习了循环，BoBo老师给他出了一系列打印图案的练习，该任务是打印用“* ”组成的“空心”正方形图案。

//输入描述 :
//多组输入，一个整数(3~20)，表示输出的行数，也表示组成正方形边的“* ”的数里。

//输出描述 :
//针对每行输入，输出用“ * ”组成的“空心”正方形，每个“* ”后面有一个空格。

//输入:4
//输出 :
//* * * *
//*     *
//*     *
//* * * *


//int main()
//{
//	int n = 0;
//	while (scanf("%d", &n) == 1)
//	{
//		int i = 0;
//		int j = 0;
//		for (i = 0; i < n; i++)
//		{
//			for (j = 0; j < n; j++)
//			{
//				if (i == 0 || i == n - 1 || j == 0 || j == n - 1)  //对需要打印*的行或列进行操作
//					printf("* ");
//				else
//				{
//					printf("  ");
//				}
//			}
//			printf("\n");
//		}
//
//	}
//	return 0;
//}



//柔性数组：在结构体中的最后一个成员包含一个个数未知的数组

//typedef struct st_type
//{
//	int i;
//	int a[0];//柔性数组成员
//	//或者int a[];
//}type_a;


//int main()
//{
//	//printf("%d", sizeof(type_a));   // 4,没算柔性数组的大小
//	//return 0;
//
//
//	//type_a s //4字节
//	//柔性数组的使用
//	//包含柔性数组的结构体使用malloc()分配内存空间,40是柔性数组的大小
//	type_a* pa = (type_a*)malloc(sizeof(type_a) + 40);    //只需要一次malloc()
//	pa->i = 10;
//
//  使用
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		pa->a[i] = i;
//	}
//
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", pa->a[i]);
//	}
//
//
//	type_a *ptr = (type_a*)realloc(pa, sizeof(type_a) + 80); //使用realloc()增加柔性数组的大小
//	if (ptr != NULL)
//	{
//		pa = ptr;
//	}
//
//	free(pa);
//	pa = NULL;
//
//	return 0;
//
//}


//第二种方式：
//struct s
//{
//	int i;
//	int* arr;
//};
//
//int main()
//{
//	struct s* ps = (struct s*)malloc(sizeof(struct s));  //一次malloc()
//	if (ps == NULL)
//	{
//		return 1;
//	}
//
//	ps->i = 100;
//	ps->arr = (int*)malloc(40);  //二次malloc()
//	if (ps->arr == NULL)
//	{
//		return 1;
//	}
//
//	//使用
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		ps->arr[i] = i;
//	}
//
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", ps->arr[i]);
//	}
//
//	//扩容
//	int* ptr = (int*)realloc(ps->arr, 80);
//	if (ptr == NULL)
//	{
//		return 1;
//	}
//	ps->arr = ptr;
//
//	//使用
//	//....
//
//	//释放
//	free(ps->arr);
//	free(ps);
//	ps = NULL;
//}


//文件的读写
//int main()
//{
//	FILE* pf = fopen("test123.txt", "r");
//	if (pf == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//	//...
//	//读文件
//
//	//文件关闭
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


// 2024.6.11

//int main()
//{
//	//FILE* pf = fopen("test.txt", "w");
//	FILE* pf = fopen("test.txt", "r");
//
//	if (pf == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//
//	//写文件
//	//char i = 0;
//	//for (i = 'a'; i < 'z'; i++)
//	//{
		//函数原型：int fputc(int c, FILE* stream);
//		fputc(i, pf);
//	//}
//
//	//读文件
//	int ch = 0;
//	while ((ch = fgetc(pf)) != EOF)
//	{
//		printf("%c\n", ch);
//	}
//
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//写一行数据
//int main()
//{
//	//以写的方式打开文件，若文件有内容，则先清空文件内容再写入新的内容
//	FILE* pf = fopen("test.txt", "w");  
//
//	if (pf == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//  函数原型：int fputs( const char *string, FILE *stream );
//	fputs("hello,bits", pf);
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//读一行数据
//int main()
//{
//	FILE* pf = fopen("test.txt", "r");
//
//	if (pf == NULL)
//	{
//		//printf("%s\n", strerror(errno));
//		perror("fopen");
//		return 1;
//	}
//
//	//读一行
//	char arr[20] = { 0 };
//	//函数原型：char *fgets( char *string, int n, FILE *stream )
//	fgets(arr, 5, pf); //会在最后加\0    内存 <- 硬盘文件
//	printf("%s\n", arr);
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//struct S
//{
//	int i;
//	float a;
//	char arr[100];
//};

//int main()
//{
//	struct S s = { 13, 23.2f, "zhansgan" };
//
//	FILE* pf = fopen("test.txt", "w");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//函数 原型：int fprintf( FILE *stream, const char *format [, argument ]...);
//	fprintf(pf, "%d %lf %s", s.i, s.a, s.arr);    //内存 -> 硬盘中的文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//int main()
//{
//	struct S s = { 0 };
//
//	FILE* pf = fopen("test.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//
//	//将内容读到s结构体中
//	fscanf(pf, "%d %f %s", &s.i, &s.a, s.arr);   //内存 <- 硬盘中的文件
//	//printf("%d %lf %s", s.i, s.a, s.arr);
//	fprintf(stdout, "%d %lf %s", s.i, s.a, s.arr);
//
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//struct S
//{
//	char arr[10];
//	int age;
//	float score;
//};
//int main()
//{
//	struct S s = { 0 };
//	//以二进制的形式读文件中
//	FILE* pf = fopen("test.txt", "rb");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//
//	//二进制的方式读
//	//函数原型：size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
//	fread(&s, sizeof(struct S), 1, pf);
//	printf("%s %d %f", s.arr, s.age, s.score);
//
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//int main()
//{
//	struct S s = { "zhangsan", 25, 50.5f };
//	//以二进制的形式写到文件中
//	FILE* pf = fopen("test.txt", "wb");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//
//	//二进制的方式写
//  函数原型：size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
//	fwrite(&s, sizeof(struct S), 1, pf);
//
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//scanf 针对标准输入的格式化输入语句
//printf 针对标准输出的格式化输出语句

//fscanf 针对所有输入流的格式化输入语句
//fprintf 针对所有输出流的格式化输出语句

//sscanf 从一个字符串中转化成一个格式化数据
//sprintf 把一个格式化的数据转化成字符串

//struct s
//{
//	char arr[10];
//	int age;
//	float score;
//
//};
//
//int main()
//{
//	struct s s = { "zhangsan", 20, 55.5f };
//	struct s tmp = { 0 };
//
//	char buf[100] = { 0 };
//
//	//函数原型：int sprintf( char *buffer, const char *format [, argument] ... );
//	//将s中的格式化数据转换成字符串放在buf中
//	sprintf(buf, "%s %d %f", s.arr, s.age, s.score);
//
//	//"zhangsan 20 55.500000"
//	printf("%s\n", buf);
//
//	//函数原型：int sscanf( const char *buffer, const char *format [, argument ] ... );
//	//从字符串buf中获取一个格式化的数据到tmp中
//	sscanf(buf, "%s %d %f", tmp.arr, &tmp.age, &tmp.score);
//	printf("%s %d %f", tmp.arr, tmp.age, tmp.score);
//	return 0;
//}


//int main()
//{
//	FILE* pf = fopen("test.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//
//	//读文件
//	//定位文件指针,函数原型：int fseek( FILE *stream, long offset, int origin );
//	//给出文件指针当前的偏移量，函数原型：long ftell( FILE *stream );
//	fseek(pf, 2, SEEK_SET);
//	int ch = fgetc(pf);
//	printf("%c\n", ch);
//	printf("%d\n", ftell(pf));
//
//
//
//	fseek(pf, 2, SEEK_CUR);
//	ch = fgetc(pf);
//	printf("%c\n", ch);
//	printf("%d\n", ftell(pf));
//
//	//让文件指针的位置回到文件的起始位置,函数原型：void rewind( FILE *stream );
//	rewind(pf);
//	ch = fgetc(pf);
//	printf("%c\n", ch);
//	printf("%d\n", ftell(pf));
//
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int a = 10000;
//	FILE* pf = fopen("test.txt", "wb");
//	fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//#include <stdio.h>
//#include <windows.h>
////VS2013 WIN10环境测试
//int main()
//{
//	FILE* pf = fopen("test.txt", "w");
//	fputs("abcdef", pf);//先将代码放在输出缓冲区
//	printf("睡眠10秒-已经写数据了，打开test.txt文件，发现文件没有内容\n");
//	Sleep(10000);
//	printf("刷新缓冲区\n");
//	fflush(pf);//刷新缓冲区时，才将输出缓冲区的数据写到文件（磁盘）
//	//注：fflush 在高版本的VS上不能使用了
//	printf("再睡眠10秒-此时，再次打开test.txt文件，文件有内容了\n");
//	Sleep(10000);
//	fclose(pf);
//	//注：fclose在关闭文件的时候，也会刷新缓冲区
//	pf = NULL;
//	return 0;
//}


//2024.9.9
//预定义符号 __FILE__、__LINE__、__DATE__、__TIME__

//int main()
//{
//	int i = 0;
//	FILE* pf = fopen("log.txt", "w");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return EXIT_FAILURE;
//	}
//
//	for (i = 0; i < 10; i++)
//	{
//		可以用来记录log，把它写进文件中
//		fprintf(pf, "file:%s line:%d date:%s time:%s i=%d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
//
//	}
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}

//int main()
//{
//	//__STDC__：如果编译器遵循ANSI C，其值为1，否则未定义(gcc、clang【苹果维护的编译器】是遵循ANSI C标准的，而VS是不遵循的)
//	printf("%d\n", __STDC__); 
//	return 0;
//}


//不要加分号，否则容易出错
//#define MAX 1000
//#define STR "hello, bit"
//#define print printf("ok")
//int main()
//{
//	int m = MAX;
//	printf("%d\n", MAX);
//	printf("%s\n", STR);
//	print;
//	return 0;
//}

//#define CASE break;case
//
//int main()
//{
//	switch ()
//	{
//	case 1:
//	CASE 2 :
//	CASE 3 :
//	CASE 4 :
//	break;
//
//	}
//}


////使用define定义宏,写宏时不要吝啬括号，防止优先级问题导致计算错误
//#define SQUARE(X) ((X)*(X))
//
//int main()
//{
//	int r = SQUARE(5);
//	printf("%d\n", r);// 25
//
//	int a = SQUARE(5 + 1);
//	//#define SQUARE(X) X*X  只是宏替换  5+1*5+1=11
//	printf("%d\n", a);
//	return 0;
//}

//#define DOUBLE(X) ((X)+(X))
//#define M 100
//
//int main()
//{
//	//若宏定义为：#define DOUBLE(X) (X)+(X)，则以下代码可能得不到你想要的计算结果（优先级问题）
//	//10 * (3) + (3)
//	int r = 10 * DOUBLE(3);
//	//以下字符串内的内容不会被替换
//	"M";
//	"DOUBLE";
//	return 0;
//}



//#和##
//#define PRINT(N) printf("the value of " #N " is %d\n", N)  // #N 即，将参数N作为字符串给替换进去
//#define PRINT(N, FORMAT) printf("the value of " #N "is " FORMAT "\n", N)   //可以打印不同格式的内容
//int main()
//{
//	int a = 10;
//	PRINT(a, "%d");
//	//PRINT(a);
//
//	double b = 20.1f;
//	PRINT(b, "%f");
//	//替换成 printf("the value of""b""is %d\n", b)
//	//PRINT(b);
//
//	return 0;
//}


//##可以把位于它两边的符号合成一个符号
//它允许宏定义从分离的文本片段创建标识符
//#define CAT(Class, Num) Class##Num
//int main()
//{
//	int Class106 = 100;
//	printf("%d\n", CAT(Class, 106));
//	//相当于printf("%d\n", Class106);
//	return 0;
//}

//带有副作用参数的宏
//#define MAX(a, b) ((a)>(b)?(a):(b))
//
//int main()
//{
//	//int m = MAX(3, 23);
//	//printf("%d\n", m);
//
//
//	int a = 5;//6 7
//	int b = 4;//5
//	int m = MAX(a++, b++);
//	//相当于 int m = ((a++) > (b++) ? (a++) : (b++))
//	        //   6   // 5  >   4   ?  6
//	printf("m=%d\n", m);  // 6
//	printf("a=%d b=%d\n", a, b); //7 5
//	return 0;
//}



//宏和函数
//宏 没有类型限制
//#define MAX(x, y) ((x)>(y)?(x):(y))
//
//
////函数调用（参数传参，栈帧创建，函数返回）
////函数参数有限定
//int Max(int x, int y)
//{
//	return (x > y ? x : y);
//
//}

//#define MALLOC(num, type) (type*)(malloc((num)*(sizeof(type))))
//
//int main()
//{
//	int* p = (int*)malloc((10) * sizeof(int));
//	int* pf = MALLOC(10, int);  //可以实现函数中传类型
//
//}

//2024.9.10

//#define M 100
//
//int main()
//{
//	printf("%d\n", M);
//#undef M  //移除预定义标识符
//	printf("%d\n", M);
//}


//条件编译
//#include <stdio.h>
//#define __DEBUG__
//int main()
//{
//	int i = 0;
//	int arr[10] = { 0 };
//	for (i = 0; i < 10; i++)
//	{
//		arr[i] = i;
//#ifdef __DEBUG__    //若定义了__DEBUG__,则执行以下代码
//		printf("%d\n", arr[i]);//为了观察数组是否赋值成功。 
//#endif //__DEBUG__
//	}
//	return 0;
//}

//
//int main()
//{
//#if 0
//	printf("ok");
//	return  0;
//#endif
//
//}


//多分支预处理指令
//#define M 6
//int main()
//{
//#if M <5
//	printf("AAAA");
//#elif M == 6
//	printf("BBBB");
//#else
//	printf("CCCC");
//#endif
//	return 0;
//}


//判断是否被定义
//#define MAX 100
//int main()
//{
//	//#if defined(MAX)
//	//	printf("max\n");
//	//#endif
//
//	//#if !defined(MAX)
//	//	printf("max\n");
//	//#endif
//
//#ifdef MAX
//	printf("max\n");
//#endif
//
//#ifndef MAX
//	printf("max\n");
//#endif
//	return 0;
//}


//文件的包含
//#include "add.h"
//#include "add.h"
//#include "add.h"
//#include "add.h"
//#include "add.h"
//#include "add.h"
//以下为add.h的内容：使用预处理指令#ifndef、#endif，可以防止预处理得到的文件重复包含头文件的内容
// 写法一：
//#ifndef __ADD_H__
//#define __ADD_H__
//
//
//int ADD(int x, int y);
//
//#endif 

//写法二：现代写法
//pragma once  头文件 只能包含一次
//int ADD(int x, int y);

//<>和""的区别是查找的策略不同
//#include <stdio.h>
//查找策略:直接去库目录下查找
//#include "test.h"
//查找策略:先去代码所在的路径下查找,如果上面找不到，再去库目录下查找

//百度笔试题:
//写一个宏，计算结构体中某变量相对于首地址的偏移，并给出说明考察:
//offsetof宏的实现

//#include <stddef.h>
//struct S
//{
//	char c1;
//	int i;
//	char c2;
//
//};
//
//#define OFFSETOF(type, m_name)      (size_t)&(((type*)0) -> m_name)
//int main()
//{
//	struct S s = { 0 };
//	printf("%d\n", OFFSETOF(struct S, c1));
//	printf("%d\n", OFFSETOF(struct S, i));
//	printf("%d\n", OFFSETOF(struct S, c2));
//
//	//printf("%d\n", offsetof(struct S, c1));
//	//printf("%d\n", offsetof(struct S, i));
//	//printf("%d\n", offsetof(struct S, c2));
//	return 0;
//}


//箭形图案
//描述:KiKi学习了循环，BoBo老师给他出了一系列打印图案的练习，该任务是打印用“*”组成的箭形图案。I
//输入描述 :本题多组输入，每行一个整数(2~20)
//输出描述 :针对每行输入，输出用“*”组成的箭形
//输入：2
//输出：
//    *
//  **
//***
//  **
//	  *

//int main()
//{
//	int n = 0;
//	while (scanf("%d", &n) == 1)
//	{
//		//打印图案
//		//上n行
//		int i = 0;
//		for (i = 0; i < n; i++)
//		{
//			//空格
//			int j = 0;
//			for (j = 0; j < n - i; j++)
//			{
//				printf("  ");
//			}
//			//*
//			for (j = 0; j <= i; j++)
//			{
//				printf("*");
//			}
//			printf("\n");
//		}
//		//下n+1行
//		for (i = 0; i < n + 1; i++)
//		{
//			//空格
//			int j = 0;
//			for (j = 0; j < i; j++)
//			{
//				printf("  ");
//			}
//			//*
//			for (j = 0; j < n + 1 - i; j++)
//			{
//				printf("*");
//			}
//			printf("\n");
//		}
//	}
//}



//描述:公务员面试现场打分。有7位考官，从键盘输入若干组成绩，每组7个分数(百分制)，
//去掉一个最高分和一个最低分，输出每组的平均成绩。(注:本题有多组输入)
//输入描述:每一行，输入7个整数(0~100)，代表7个成绩，用空格分隔。
//输出描述 :每一行，输出去掉最高分和最低分的平均成绩，小数点后保留2位，每行输出后换行。
//
//示例1
//输入 : 99 45 78 67 72 88 60
//输出 : 73.00


//int main()
//{
//	int score = 0;
//	int n = 0;
//	int min = 100;
//	int max = 0;
//	int sum = 0;
//	while (scanf("%d", &score) == 1)
//	{
//		n++;
//		if (score > max)
//			max = score;
//		if (score < min)
//			min = score;
//		sum += score;
//		if (n == 7)
//		{
//			printf("%.2lf", (sum - max - min) / 5.0);
//			n = 0;
//			max = 0;
//			min = 100;
//			sum = 0;
//		}
//
//	}
//	return 0;
//}



//在32位系统环境，编译选项为4字节对齐，那么sizeof(A)和sizeof(B)是()
//struct A
//{
//	int A;  // 0-3
//	short b; //4-5
//	int c;  //8-11
//	char d; // 12
//	//13-15
//};
//
//struct B
//{
//	int a;  //0-3
//	short b; // 4-5
//	char c;  //6
//	int d;   //8-11
//};
//
//int main()
//{
//	printf("%d\n", sizeof(struct A)); //16
//	printf("%d\n", sizeof(struct B)); //12
//	return 0;
//}

//#pragma pack(4)//编译选项，表示4字节对齐平台
//int main(int argc, char* argv[])
//{
//	struct tagTest1
//	{
//		short a;
//		char d;
//		long b;
//		long c;
//	};
//	struct tagTest2
//	{
//		long b;
//		short c;
//		char d;
//		long a;
//	};
//	struct tagTest3
//	{
//		short c;
//		long b;
//		char d;
//		long a;
//	};
//	struct tagTest1 stT1;
//	struct tagTest2 stT2;
//	struct tagTest3 stT3;
//	printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3));  //12 12 16
//	return 0;
//
//}
//#pragma pack()


//#define MAX_SIZE A+B
//struct _Record_Struct
//{
//	//位段：一个单元一个单元来开辟，不够用的则新开辟一个单元
//	unsigned char Env_Alarm_ID: 4; // 开辟一个char字节
//	unsigned char Paral : 2;       // 
//    unsigned char state;           //开辟一个char字节 
//    unsigned char avail : 1;       //开辟一个字节
//}*Env_Alarm_Record;   //共占3个字节
//
//struct _Record_struct* pointer = (struct _Record_struct*)malloc(sizeof(struct _Record_struct)*MAX_SIZE);
//struct _Record_struct* pointer = (struct _Record_struct*)malloc(sizeof(struct _Record_struct)*2+3);  
//当A = 2，B = 3时，pointer分配()个字节的空间    答案：9个字节


//int main()
//{
//	unsigned char puc[4];
//	struct tagPIM
//	{
//		unsigned char ucPim1;
//		unsigned char ucData0 : 1; //只占1位
//		unsigned char ucDatal : 2; //只占2位
//		unsigned char ucData2 : 3; //只占3位
//	}*pstPimData;
//	pstPimData = (struct tagPIM*)puc;
//
//	memset(puc, 0, 4);
//	pstPimData->ucPim1 = 2;
//	pstPimData->ucData0 = 3;  // 3->011   只要1
//	pstPimData->ucDatal = 4;  // 4->100   只要00
//	pstPimData->ucData2 = 5;  // 5->101   要101
//	printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]); // 02 29 00 00
//	return 0;
//}


//在VS2013下，这个结构体所占的空间大小是( 12 )字节
//typedef struct {
//	int a;
//	char b;
//	short c;
//	short d;
//}AA_t;


//#include<stdio.h>
//union Un
//{
//	short s[7]; //14
//	int ns;     //4
//};
//int main()
//{
//	printf("%d\n", sizeof(union Un)); //共用体也存在对齐，16
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	union
//	{
//		short k;   //2字节
//		char i[2]; //2字节
//	}*s, a;  //该共用体占2字节
//
//	s = &a;
//	s->i[0] = 0x39;    // i[] = 39 38  低地址 -> 高地址
//	s->i[1] = 0x38;
//	printf(" % x\n", a.k);  //访问a.k其实就是访问i[0]和i[1]，因为这是共用体。小端字节序：低位地址低字节，即  0x38 39
//	return 0;
//}


//enum en
//{
//	X1,		//0
//	Y1,		//1
//	Z1 = 255,
//	A1,		//256
//	B1,		//257
//};
//
//int main()
//{
//	enum en A = Y1;  // 1
//	enum en B = B1;  // 257
//	printf(" % d % d\n", A, B);   
//
//}


//void GetMemory char
//{
//	p = (char*)malloc(100);
//
//}
//void Test void
//{
//	char* str = NULL; 
//	GetMemory(str); 
//	strcpy(str, "hello world");
//	printf(str);
//
//}


//char* GetMemory(void)
//{
//	char p[] = "hello world";
//	return p;
//}
//void Test(void)
//{
//	char* str = NULL;
//	str = GetMemory();    //函数返回时，p指针所指向的内容已经被销毁
//	printf(str);
//}


//题目名称:找单身狗
//题目内容：一个数组中只有两个数字是出现一次，其他所有数字都出现了两次。
//编写一个函数找出这两个只出现一次的数字。

//void find_single_dog(int arr[], int sz, int* pd1, int* pd2)
//{
//	int i = 0;
//	int ret = 0;
//	//1.所有内容进行异或
//	for (i = 0; i < sz; i++)
//	{
//		ret ^= arr[i];
//	}
//	//2.计算ret的二进制中左右边的第几位是1
//	int pos = 0;
//	for (pos = 0; pos < 32; pos++)
//	{
//		if (((ret >> pos) & 1) == 1)
//		{
//			break;
//		}
//	}
//	for (i = 0; i < sz; i++)
//	{
//		if (((arr[i] >> pos) & 1) == 1)
//		{
//			*pd1 ^= arr[i];
//		}
//		else
//		{
//			*pd2 ^= arr[i];
//		}
//	}
//}
//int main()
//{
//	//异或：0^a = a, a^a=0
//	//分组
//	//1.所有数字异或
//	//2.找出异或的结果数字中哪一位为1  -n
//	//3.以第n为1，分一组，第n位为0分一组
//
//	int arr[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 6 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int dog1 = 0;
//	int dog2 = 0;
//	find_single_dog(arr, sz, &dog1, &dog2);
//	printf("%d %d", dog1, dog2);
//	return 0;
//}


//#include <stdlib.h>
//#include <assert.h>
//实现atoi函数
//1.空指针
//2.空字符串
//3.空格
//4.+-
//5.越界
//6.非数字字符

//enum Status
//{
//	VALID,
//	INVALID
//}sta = INVALID;
//
//int my_atoi(const char* str)
//{
//	int flag = 0;
//	assert(str);
//	if (*str == '\0')
//		return 0;//非法0
//
//	//跳过空白字符
//	while (isspace(*str))
//	{
//		str++;
//	}
//	//+-
//	if (*str == '+')
//	{
//		flag = 1;
//		str++;
//	}
//	else if (*str == '-')
//	{
//		flag = -1;
//		str++;
//	}
//	long long ret = 0;
//	while (*str)
//	{
//		if (isdigit(*str))
//		{
//			//越界
//			ret = ret * 10 + flag * (*str - '0');
//			if (ret > INT_MAX || ret < INT_MIN)  //整型最大值，整型最小值
//			{
//				return 0;
//			}
//		}
//		else
//		{
//			return (int)ret;
//		}
//		str++;
//	}
//	if (*str == '\0')
//	{
//		sta = VALID;
//	}
//	return (int)ret;
//}
//
//int main()
//{
//	char arr[2000] = "-123abc456";
//	//int ret = atoi(arr);   //将字符串转换成整型
//	int ret = my_atoi(arr);
//
//	if (sta == INVALID)
//	{
//		printf("非法转换:%d\n", ret);
//
//	}
//	else if (sta == VALID)
//	{
//		printf("合法转换:%d\n", ret);
//	}
//	//printf("%d\n", ret);
//	return 0;
//}
//
////说明以下函数作用
//int main()
//{
//	long num = 0;
//	FILE* fp = NULL;
//	if ((fp = fopen("fname.dat", "r")) == NULL)
//	{
//		printf("can't open the file! ");
//		exit(0);// 直接退出，下面代码将不会执行
//	}
//	while (fgetc(fp) != EOF)
//	{
//		num++;
//	}
//	printf("num=%d\n", num);
//	fclose(fp);
//	return 0;
//}


//2024.9.11

//#define INT_PTR int*
//typedef int* int_ptr;

//预处理指令，直接替换，即int *a, b
//INT_PTR a, b; //a的类型是int*，b的类型是int

//typedef类型重命名，是一个独立可用的类型
//int_ptr c, d;//c和d都是指针类型

//typedef char* char_ptr;
//int main()
//{
//	char* a, b; // a为char*类型，b为char类型
//	char_ptr c, d;  //c,d均为char*类型
//	printf("%d %d\n", sizeof(a), sizeof(b));
//	printf("%d %d\n", sizeof(c), sizeof(d));
//	return 0;
//}

//#define N 4
//#define Y(n)((N+2)*n)/*这种定义在编程规范中是严格禁止的*/
//则执行语句:z = 2 * (N + Y(5 + 1)); 后，z的值为(70)


//#define A 2+2
//#define B 3+3
//#define C A*B
//int main()
//{
//	printf("%d\n", C);
//	return 0;
//
//}



//写一个宏，可以将一个整数的二进制位的奇数位和偶数位交换。
//把偶数位提取出来再左移一位，把奇数位提取出来再右移一位，最后再相加
//#define SWAP_BIT(n)  (((n&0x55555555)<<1) + (((n&0xaaaaaaaa)>>1)))  
//
//int main()
//{
//	//交换前：1010 -10
//	//交换后：0101 -5
//
//	//交换前：-2
//	//交换后：-3
//	int n = 0;
//	scanf("%d", &n);
//	printf("%d\n", SWAP_BIT(n));
//	return 0;
//
//}


//#include<stdio.h>
//int main()
//{
//	unsigned char i = 7;   // unsigned char >= 0
//	int j = 0;
//	for (; i > 0; i -= 3)  // i=-2时，i其实是254   i = 7  4  1  254   251 ... 5   2  
//	{                      // i=-1时，i其实是255   i = 255  253  250  ...  6   3   0 
//		++j;
//	}
//	printf("%d\n", j);     //173
//	return 0;
//}



////当输入1abcedf2df时，输出为1AbCeDf2dF
//#include<stdio.h>
//int main()
//{
//	char a = 0, ch;
//	while ((ch = getchar()) != '\n')
//	{
//		//a不为偶且ch为小写字母时-> 变大写；a为偶时直接输出
//		if (a % 2 != 0 && (ch >= 'a' && ch <= 'z'))
//			ch = ch - "a" + "A";
//		a++;
//		putchar(ch);
//	}
//	printf("\n");
//	return 0;
//}


//在#pragma.pack(4)和#pragma pack(8)的情况下，结构体的大小分别是(16, 16, 16, 24)
//struct One {
//	double d;
//	char c;
//	int i;
//};
//
//struct Two {
//	char c;
//	double d;
//	int i;
//};


//死循环
//int x = 1; 
//do
//{
//	printf("%2d\n", x++); 
//}while (x--);

//#include<stdio.h>
//#include<stdlib.h>
//void main()
//{
//	int a = -3;   
//	unsigned int b = 2; 
//	long c = a + b;    //a+b结果为无符号数，但是long是有符号的，因此打印出来也是有符号的
//	printf("%ld\n",c); // -1
//}  

//设有定义char* p[]={ "Shanghai","Beijing","Honkong”};则结果为j字符的表达式是(*(p[1]+3))


//int f(int x) {
//	return((x > 2) ? x * f(x - 1) : 3);
//}
//
//int i; 
//i = f(f(2)); //i = 9


//int p[][4] = { {1},{3,2},{4,5,6},{0} };中，P[1][2]的值是(0)


//int fun(int a) {
//	a ^= (1 << 5) - 1;
//	return a;
//}
//fun(21)=10 

//下列关于C / C++的宏定义，不正确的是(B)
//A.宏定义不检查参数正确性，会有安全隐患
//B.宏定义的常量更容易理解，如果可以使用宏定义常量的话，要避免使用const常量
//C.宏的嵌套定义过多会影响程序的可读性，而且很容易出错
//D.相对于函数调用，宏定义可以提高程序的运行效率


//下面关于“指针”的描述不正确的是(A)
//A 当使用free释放掉一个指针内容后, 指针变量的值被置为NULL
//B.32位系统下任何类型指针的长度都是4个字节
//C.指针的数据类型声明的是指针实际指向内容的数据类型
//D.野指针是指向未分配或者已经释放的内存地址

//由多个源文件组成的C程序，经过编辑、预处理、编译、链接等阶段会生成最终的可执行程序。
//下面哪个阶段可以发现被调用的函数未定义(C)
//A.预处理
//B.编译
//C.链接
//D.执行


//#define N 3+1
//#define Y(n)((N+1)*n)
//则执行语句 z=2*(N+Y(5+1))后，z的值为(60)


//char a; int b; float c; double d;则表达式 a*b+d-c 值的类型为(Double)
//解释：
//自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换，这种转换不需要程序员干预，会自动发生。
//1.将一种类型的数据赋值给另外干种类型的变量时就会发生自动类型转换，如:float f = 100;
//100是 int类型，会自动转换成 foat，再赋值给f
//2.在不同类型的混合运算中，编译器也会自动地转换数据类型，将参与运算的所有数据先转换为同一种类型，然后再进行计算。
//转换的规则如下:
//a.转换按数据长度增加的方向进行，以保证数值不失真，或者精度不降低。例如，int 和 long 参与运算时，先把 int 类型的数据转成 long 类型后再进行运算。
//所有的浮点运算都是以双精度进行的，即使运算中只有 foat 类型，也要先转换为 double 类型，才能进行运算。
//char 和 short 参与运算时，必须先转换成 int 类型。


//编程题：
//Fibonacci数列是这样定义的:
//F[0] = 0
//F[1] = 1
//for each i≥ 2 : F[i] = F[i - 1] + F[i - 2]
//因此，Fibonacci数列就形如 : 0, 1, 1, 2, 3, 5, 8, 13, …，在Fibonacci数列中的数我们称Fibonacci数。
//给你一个N，你想让其变为一个Fibonacci数，每一步你可以把当前数字X变为X - 1或者X + 1，
//现在给你一个数N求最少需要多少步可以变为Fibonacci数。

//#include <stdio.h>
//#include <math.h>
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int a = 0;
//	int b = 1;
//	int c = a + b;
//	while (1)
//	{
//		if (n == b)
//		{
//			printf("0\n");
//			break;
//		}
//		else if (n < b)
//		{
//			if (abs(a - n) > abs(b - n))  //abs()绝对值
//			{
//				printf("%d\n", abs(b - n));
//				break;
//			}
//			else
//			{
//				printf("%d\n", abs(a - n));
//				break;
//			}
//		}
//		c = a + b;
//		a = b;
//		b = c;
//
//
//	}
//	return 0;
//}


//请实现一个函数，将一个字符串中的每个空格替换成“ % 20"。
//例如，当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 


#include <stdio.h>
void replaceSpace(char* str, int length)
{
	char* cur = str;
	int space_count = 0;
	while (*cur)
	{
		if (*cur == ' ')
			space_count++;
		cur++;
	}
	int end1 = length - 1;
	int end2 = length + space_count * 2 - 1;
	while (end1 != end2)
	{
		if (str[end1] != ' ')
		{
			str[end2--] = str[end1--];
		}
		else
		{
			end1--;
			str[end2--] = '0';
			str[end2--] = '2';
			str[end2--] = '%';

		}
	}

}

int main()
{
	char str[100] = "we are family.";
	int length = strlen(str);
	replaceSpace(str, length);
	printf("%s\n", str);

}